SPECTRWM(1)
πΈ NAME πΈ
spectrwm β window manager for X11 β is the bestie from the General Commands Manual, and she's here to be smol, fast, and out of your way. π
β¨ SYNOPSIS β¨
spectrwm [-c file] [-v]
π OPTIONS π
-cfile β tells spectrwm to load this config file instead of going on its little scan for one. ποΈ-dβ debug mode goes brrr: enables debug mode and logging tostderr. πͺ΅-vβ prints the version and exits, iconic. π
π DESCRIPTION π
okay so spectrwm is a minimalistic window manager that literally tries to stay out of the way so your valuable screen real estate can be used for much more important stuff. It has sane defaults and does not require you to learn a language to do any configuration. It was written by hackers for hackers and it strives to be small, compact and fast. no cap. β¨
When spectrwm starts up, it reads settings from its configuration file, spectrwm.conf. See the βCONFIGURATION FILESβ section below. π«Ά
The following notation is used throughout this page:
M Meta
S Shift
β¨Nameβ© Named key or button
spectrwm is very simple in its use. Most of the actions are initiated via key or pointer button bindings. See the βBINDINGSβ section below for defaults and customizations. πΉ
π¦ CONFIGURATION FILES π¦
okay bestie, spectrwm looks for the user-configuration file in this exact order:
$XDG_CONFIG_HOME/spectrwm/spectrwm.conf~/.config/spectrwm/spectrwm.conf(if$XDG_CONFIG_HOMEis either not set or empty)~/.spectrwm.conf.
If the user-configuration file is not found, spectrwm then looks for the global configuration file in the following order:
$XDG_CONFIG_DIRS/spectrwm/spectrwm.conf(each colon-separated directory in$XDG_CONFIG_DIRS)/etc/xdg/spectrwm/spectrwm.conf(if$XDG_CONFIG_DIRSis either not set or empty)/etc/spectrwm.conf
The format of the file is
keyword = setting
Where β=β may be replaced with β+=β or β-=β, if supported by the option. π
For example:
color_focus = red
quirk[XTerm] += FLOAT
Enabling or disabling an option is done by using 1 or 0 respectively. π
Colors need to be specified per the XQueryColor(3) specification. In addition, alpha transparency may be specified via the format rbga:red/green/blue/alpha (8-bit hex values). For example, to specify a 50% transparent blue status bar background:
bar_color = rgba:00/00/ff/7f
Note that a compositing manager is required for alpha transparency. π«§
Mark option values may be wrapped in single/double quotes to prevent whitespace trimming, specify empty strings, etc. Literal quote/backslash characters can be escaped with a backslash \, when needed. πͺ
Comments begin with a #. When a literal β#β is desired in an option, then it must be escaped with a backslash, i.e. \#. π―οΈ
The file supports the following keywords:
autorun
Launch an application in a specified workspace at start-of-day. Defined in the format ws[idx]:application, e.g. ws[2]:xterm launches an xterm(1) in workspace 2. Specify ws[-1] to launch applications such as desktop managers and panels in free mode to keep them always mapped. π
Note that libswmhack.so is required for "spawn-in-workspace" behavior. See the βSWMHACKβ section below for more information, tips, and workarounds if a program fails to spawn in the specified workspace. π§
bar_action
External script that populates additional information in the status bar, such as battery life. π
bar_action_expand
Process bar_format character sequences in bar_action output; default is 0. π
bar_at_bottom
Place the statusbar at the bottom of each region instead of the top. Default is 0. β¬οΈ
bar_border[x]
Border color of status bar(s) on screen number x. Default is rgb:00/80/80. πΌοΈ
bar_border_free[x]
Border color of a status bar for a focused region on screen number x when a workspace-free window is focused. Default is rgb:80/80/00. πΌ
bar_border_unfocus[x]
Border color of status bar(s) for unfocused region(s) on screen number x. Default is rgb:00/40/40. π΄
bar_border_width
Set status bar border thickness in pixels. Disable border by setting to 0. π
bar_color[x]
Background color of status bar(s) on screen number x. π¨
A comma-separated list of multiple colors can be specified. The first value is used as the default background color. Any of these colors can then be selected as a background color in the status bar through the use of the markup sequence +@bg=n; where n is the color index counting from 0. π
bar_color_free[x]
Background color of a status bar for a focused region on screen number x when a workspace-free window is focused. πΈ
A comma-separated list of multiple colors can be specified, with the same syntax and behavior as bar_color. Default is rgb:40/40/00. π
Note thatbar_colordefines the background color indices that can be used inbar_formatmarkup sequences and is the fallback for colors that are left unspecified in this option. π‘
bar_color_selected[x]
Background color for selected menu items on screen number x. Defaults to the value of bar_border. π
bar_color_unfocus[x]
Background color of status bar(s) for unfocused region(s) on screen number x. π΄
A comma-separated list of multiple colors can be specified, with the same syntax and behavior as bar_color for unfocused bar(s). Defaults to the value of bar_color. π«Ά
Note thatbar_colordefines the background color indices that can be used inbar_formatmarkup sequences and is the fallback for colors that are left unspecified in this option. π‘
bar_enabled
Set default bar_toggle state; default is 1. β
bar_enabled_ws[x]
Set default bar_toggle_ws state on workspace x; default is 1. β
bar_font
Fonts used in the status bar. Either Xft or X Logical Font Description (XLFD) may be used to specify fonts. Fallback fonts may be specified by separating each font with a comma. If all entries are in XLFD syntax, font set will be used. If at least one entry is Xft, Xft will be used. π€
The default is to use font set. π °οΈ
If Xft is used, a comma-separated list of multiple fonts can be specified. The first entry is the default font. Any font defined here can then be selected in the status bar through the use of the markup sequence +@fn=n; where n is the font index counting from 0. π’
Also note that dmenu(1) prior to 4.6 does not support Xft fonts. π«’
Xft examples:
bar_font = Terminus:style=Regular:pixelsize=14:antialias=true
bar_font = -*-profont-medium-*-*-*-11-*-*-*-*-*-*-*,Terminus:pixelsize=14,-*-clean-medium-*-*-*-12-*-*-*-*-*-*-*
Font set examples:
bar_font = -*-terminus-medium-*-*-*-14-*-*-*-*-*-*-*
bar_font = -*-profont-medium-*-*-*-11-*-*-*-*-*-*-*,-*-terminus-medium-*-*-*-14-*-*-*-*-*-*-*,-*-clean-medium-*-*-*-12-*-*-*-*-*-*-*
To list the available fonts in your system see fc-list(1) or xlsfonts(1) manpages. The xfontsel(1) application can help with the XLFD setting. π§°
bar_font_color[x]
Foreground color of the status bar(s) on screen number x. π
A comma-separated list of multiple colors can be specified. The first value is used as the default foreground color. Any of these colors can then be selected as a foreground color in the status bar through the use of the markup sequence +@fg=n; where n is the color index counting from 0. β¨
bar_font_color_free[x]
Foreground color of a status bar for a focused region on screen number x when a workspace-free window is focused. πΌ
A comma-separated list of multiple colors can be specified, with the same syntax and behavior as bar_font_color. Default is rgb:ff/ff/ff. π€
Note thatbar_font_colordefines the foreground color indices that can be used inbar_formatmarkup sequences and is the fallback for colors that are left unspecified in this option. π‘
bar_font_color_unfocus[x]
Foreground color of status bar(s) for unfocused region(s) on screen number x. π΄
A comma-separated list of multiple colors can be specified, with the same syntax and behavior as bar_font_color for unfocused bar(s). Defaults to the value of bar_font_color. π«Ά
Note thatbar_font_colordefines the foreground color indices that can be used inbar_formatmarkup sequences and is the fallback for colors that are left unspecified in this option. π‘
bar_font_color_selected[x]
Foreground color for selected menu items on screen number x. Defaults to the value of bar_color. π
bar_font_pua
Specify a font to override the Unicode Private Use Area code points (U+E000 -> U+F8FF, U+F0000 -> U+FFFFD, U+100000 -> U+10FFFD). Some fonts use these code points to provide special icon glyphs. Available only with Xft fonts. π§
bar_format
Set the bar format string, overriding clock_format and all of the enabled options. The format is passed through strftime(3) before being used. It may contain the following character sequences: π
+<β Pad with a space+Aβ Output of the external script+Cβ Window class (fromWM_CLASS)+Dβ Workspace name+Fβ Focus status indicator+Iβ Workspace index+Lβ Workspace list indicator+Mβ Number of iconic (minimized) windows in workspace+Nβ Screen number+Pβ Window class and instance separated by a colon+Rβ Region index+Sβ Stacking algorithm+Tβ Window instance (fromWM_CLASS)+Uβ Urgency hint+Vβ Program version+wβ Number of windows in workspace+Wβ Window name (from_NET_WM_NAME/WM_NAME)+|[weight][justify]β Begin new section and reset markup sequence effects.
Okay so, the weight is a positive integer used to allocate horizontal space between 'L', 'C' and 'R' sections (peep the justify option if you're lost). The default weight is 1. π
justify can have the value L, C, R or T. L, C, R are for left, center and right justified sections respectively. A T section will limit its space usage to fit to the text. If no value is specified for a given section, the setting from bar_justify is used.
Also in the format-specifier mix:
++β a literal β+β+@β prefix for text markup sequences
The currently recognized text markup sequences are:
+@fn=n;β selects font n (starting at 0) frombar_font.+@fg=n;β selects foreground color n (starting at 0) frombar_font_color.+@bg=n;β selects background color n (starting at 0) frombar_color.+@stp;β stops the interpretation of markup sequences. Any markup sequence found after+@stpwill appear as normal characters in the status bar.
Heads up bestie: markup sequences in bar_action script output will only be processed if bar_action_expand is enabled. π«Ά
All character sequences may limit its output to a specific length, for example +64A. By default, no padding/alignment is done in case the length of the replaced string is less than the specified length (64 in the example). The padding/alignment can be enabled using a _ character in the sequence. For example: +_64W, +64_W and +_64_W enable padding before (right alignment), after (left alignment), and both before and after (center alignment) window name, respectively. Any characters that do not match the specification are copied as-is.
bar_justifyβ Justify the status bar text. Possible values areleft,center, andright.
Note that if the output is not left justified, it may not be properly aligned in some circumstances, due to the white-spaces in the default static format. See the bar_format option for more details.
bar_padding_horizontalβ Set status bar horizontal padding in pixels; default is0.bar_padding_verticalβ Set status bar vertical padding in pixels; default is0.bar_workspace_limitβ Set the maximum workspace index (counting from 1) to list in the status bar workspace (+L) and urgency hint (+U) indicators. Workspaces beyond this value will not be shown. Default is0(disabled).bind[x]β Bind key or button combo to action x. See the βBINDINGSβ section below.border_widthβ Set window border thickness in pixels. Disable all borders by setting to0.boundary_widthβ Set region containment boundary width in pixels. This is how far a window must be dragged/resized (with the pointer) beyond the region edge before it is allowed outside the region. Disable the window containment effect by setting to0.cancelkeyβ Change the key used as an alternative means of terminating move/resize operations. Default isEscape.
See the βBINDINGSβ section below for details on how to find key names.
center_adaptiveβ In centered mode, enable to center the master area only when centering does not create empty space (e.g., with one stack, revert to non-centered). Default is0.center_autobalanceβ Automatically balance the master/stacking areas when toggling centered mode. Default is0.center_noautostackβ In centered mode, an extra stack is automatically added when there is only one stack. Disable the automatic stack by setting to1. Can be used in combination withcenter_adaptiveto only center the master area when there are at least two stacks. Default is0.center_nowrapβ In centered mode, stacks are positioned from one side of the master area and spillover to the opposite side. Enable to maintain the original order of stacks, split by the master area without wrapping. Default is0.click_to_raiseβ Enable or disable raising stacking priority when clicking on a window. Default is1.clock_enabledβ Enable or disable displaying the clock in the status bar. Disable by setting to0so a custom clock could be used in thebar_actionscript.color_focus_freeβ Border color of the currently focused window that is in free mode. Default isyellow.color_focus_maximized_freeβ Border color of the currently focused maximized window that is in free mode. Defaults to the value ofcolor_focus_free.color_unfocus_freeβ Border color of unfocused windows that are in free mode, default isrgb:88/88/00.color_unfocus_maximized_freeβ Border color of unfocused maximized windows that are in free mode. Defaults to the value ofcolor_unfocus_free.color_urgent_freeβ Border color of urgent windows that are in free mode. Defaults to the value ofcolor_unfocus_free.color_urgent_maximized_freeβ Border color of urgent maximized windows that are in free mode. Defaults to the value ofcolor_urgent_free.color_focusβ Border color of the currently focused window. Default isred.color_focus_maximizedβ Border color of the currently focused, maximized window. Defaults to the value ofcolor_focus.color_unfocusβ Border color of unfocused windows, default isrgb:88/88/88.color_unfocus_maximizedβ Border color of unfocused, maximized windows. Defaults to the value ofcolor_unfocus.color_urgentβ Border color of urgent windows. Defaults to the value ofcolor_unfocus.color_urgent_maximizedβ Border color of urgent, maximized windows. Defaults to the value ofcolor_urgent.cycle_visibleβ Include workspaces that are mapped when switching withws_next,ws_prev,ws_next_all,ws_prev_all,ws_next_move, orws_prev_move. Enable by setting to1.
Note that mapped workspaces will be swapped unless workspace_clamp is enabled. If warp_focus is also enabled, focus will go to the region where the workspace is mapped.
dialog_ratioβ Some applications have dialogue windows that are too small to be useful. This ratio adjusts the window/region size ratio for transient windows having theTRANSSZquirk. For example,0.6is 60% of the monitor size if the current region spans the monitor.disable_borderβ Remove border when bar is disabled and there is only one window on the region. Enable by setting to1. Setting this toalwaysremoves the border regardless of the bar being enabled/disabled. Defaults to0.disable_paddingβ Remove region padding when the bar is disabled and there is only one window on the region. Enable by setting to1. Setting this toalwaysremoves the region padding regardless of the bar being enabled/disabled. Defaults to0.focus_closeβ Window to put focus when the focused window is closed. Possible values arefirst,next,previous(default),lastandprior.nextandpreviousare relative to the window that is closed.prioris the last focused window in the workspace.focus_close_wrapβ Whether to allow the focus to jump to the last window when the first window is closed or vice versa. Disable by setting to0.focus_defaultβ Window to put focus when no window has been focused. Possible values arefirstandlast(default).focus_mark_noneβ Set thebar_formatfocus status indicator (+F) string to substitute when no window is focused. Default is''.focus_mark_normalβ Set thebar_formatfocus status indicator (+F) string to substitute when a normal (not floating, maximized or free) window is focused. Default is''.focus_mark_floatingβ Set thebar_formatfocus status indicator (+F) string to substitute when a floating window is focused. Default is'(f)'.focus_mark_freeβ Set thebar_formatfocus status indicator (+F) string to substitute when a window that is in free mode is focused. Default is'(*)'.focus_mark_maximizedβ Set thebar_formatfocus status indicator (+F) string to substitute when a maximized window is focused. Default is'(m)'.focus_mode[t]β Set window focus behavior with respect to the pointer. Possible values:defaultβ Set window focus on border crossings caused by cursor motion and window interaction.followβ Prioritize the pointer location. Set window focus on all cursor border crossings, including workspace switches and changes to layout.manualβ Ignore the pointer location. Set window focus on window interaction only.
Optionally, it is possible to adjust the focus mode for specific focus situations. A comma-separated list of the following situations can be specified for t:
borderβ pointer enters a window β¨ Default isfollow.configureβ window position and/or size got changed by the client or by EWMH π«Ά Default ismanual.iconifyβ window got iconified π€ Default ismanual.layoutβ the workspace layout changed π§ Default ismanual.mapβ window maps (aka it shows up, hi bestie π) Default ismanual.moveβ window got moved to another workspace π Default ismanual.startupβ spectrwm (re)started π Default ismanual.uniconifyβ window got un-iconified, welcome back πΈ Default ismanual.unmapβ window unmaps π» Default ismanual.workspaceβ workspace got switched π₯οΈ Default ismanual.
Quick note, bestie: when t is left out entirely, the setting you give gets slapped onto all the focus situations. Like so:
focus_mode = follow # Set all focus situations to 'follow'.
focus_mode[map,unmap] = manual # Change only map and unmap to 'manual'.
focus_mode = default # Reset all focus situations to respective default values.
fullscreen_hide_otherβ when a fullscreen window is focused and is not in the below state, hide all the unrelated windows in that same workspace π super useful for transparent windows, ngl. Defaults to0.fullscreen_unfocusβ sets what happens when a fullscreen window loses focus π possible values are:noneβ leave the window fullscreen. (default)restoreβ exit fullscreen.iconifyβ minimize/hide the window.floatβ exit fullscreen and float the window.belowβ set the below state on the window.quick_belowβ set the below state on the window, and unset it when it gets refocused.
Heads up π this option is ignored in max layout.
iconic_enabledβ show the number of iconic (minimized) windows in the status bar π turn it on by setting it to1.keyboard_mappingβ clears all key bindings (button bindings stay, they're safe π«Ά) and loads fresh bindings from the file you point it at. This is the glow-up that lets you load pre-defined key bindings for your keyboard layout β¨οΈβ¨ See the βKEYBOARD MAPPING FILESβ section below for the list of keyboard mapping files that come provided for several layouts.
Also note: you can pass /dev/null here if you only want to clear bindings, no reload. Clean slate energy π
layoutβ picks the layout to use at start-of-day π¬ defined in the formatws[idx]:master_grow:master_add:stack_inc:always_raise:stack_mode, e.g.ws[2]:-4:0:1:0:horizontalsets workspace 2 to thehorizontalstack mode, shrinks the master area by 4 ticks, and adds one window to the stack β all while keeping the default floating window behavior. Possiblestack_modevalues arevertical,vertical_flip,vertical_center,vertical_center_flip,horizontal,horizontal_flip,horizontal_center,horizontal_center_flip,maxandfloating.
See master_grow, master_shrink, master_add, master_del, stack_inc, stack_dec, stack_balance, and always_raise for more info π Note that the stacking options are complicated and have side-effects β one should really familiarize oneself with these commands before experimenting with the layout option. Fr fr, don't just yolo it π
This setting is not retained at restart.
layout_orderβ defines the layout sequence that thecycle_layoutaction walks through π possible values arevertical,horizontal,maxandfloating. At least one value must be specified, and no duplicates bestie π The default isvertical,horizontal,max,floating.max_layout_maximizeβ automatically maximize windows inmaxlayout πͺ note that the automatic maximize behavior is disabled for windows that get unmaximized inmaxlayout. Maximizing the window or resetting the layout withstack_resetturns it back on β¨ enabled by default. Disable it by setting to0.maximize_hide_barβ when set to1,maximize_togglewill also hide/restore the bar visibility of the affected workspace π Defaults to0.maximize_hide_otherβ when a maximized window is focused and is not in the below state, hide unrelated windows in the same workspace π great for transparent windows. Defaults to0.maximized_unfocusβ sets what happens when a maximized window loses focus π possible values:noneβ leave the window maximized.restoreβ unmaximize the window. (default)iconifyβ minimize/hide the window.floatβ unmaximize and float the window.belowβ set the below state on the window.quick_belowβ set the below state on the window, and unset it when refocused.
Same deal as before π«Ά this option is ignored in max layout.
modkeyβ changes the current modifier value ofMODinbindentries that come later in the config file π for existing bindings, the new value gets substituted in for the previous one. Possible values areMod1(default),Mod2,Mod3,Mod4andMod5.
Mod1 is generally the Alt key, Mod2 is the Command key on macOS, and Mod4 is the Windows key on a PC π₯οΈ you can find the current modifier key mapping by running xmodmap(1).
move_stepβ sets the pixel amount to move a window for themove_left,move_right,move_up, andmove_downactions π Default is50.nameβ sets the name of a workspace at start-of-day π·οΈ defined in the formatws[idx]:name, e.g.ws[1]:Consolesets the name of workspace 1 to βConsoleβ.program[p]β defines a new action to spawn a programpπ see the βPROGRAMSβ section below.quirk[c[:i[:n[:t]]]]β adds a βquirkβ for windows with classc, instancei(optional), namen(optional), and typet(optional) π¦ see the βQUIRKSβ section below.regionβ allocates a custom region, removing any autodetected regions that occupy the same space on the specified logical X screen number πΊοΈ defined in the formatscreen[idx]:widthxheight+x+y[,rotation], e.g.screen[1]:800x1200+0+0orscreen[1]:800x1200+0+0,inverted(with the optional rotation).
Wanna make a region span multiple monitors? Just make a region big enough to cover them all π
e.g. screen[1]:2048x768+0+0 makes the region span two monitors with 1024x768 resolution sitting one next to the other.
Possible values for that optional rotation argument are normal (default), left, inverted and right. Note that rotation is used by workspace_autorotate π
region_paddingβ pixel width of the empty space inside region borders π disable it by setting to0.resize_stepβ sets the pixel amount to resize a window for thewidth_shrink,width_grow,height_shrink, andheight_growactions π Default is50.snap_rangeβ sets the distance in pixels a tiled/maximized window has to be moved (with the pointer) before it unsnaps and floats freely πͺ set to0to unsnap immediately. Default is25.spawn_flags[p]β if the search patternpis specified, change the spawn flags of existing program entries π ifpis omitted, change the default spawn flags for anyprogramorautorunentries that come later in the config file. Note thatpis interpreted as a POSIX Extended Regular Expression.
One or more of these flags can be given in a comma-separated list:
nospawnwsβ when the program is spawned, don't associate the spawn workspace with the program's windows.xterm_fontadjβ enables automatic font size adjustments when resizingxterm(1)windows π€ note that this works in conjunction with theterm_widthoption and theXTERM_FONTADJquirk. See theterm_widthoption and the βQUIRKSβ section for more info.optionalβ disable program validation.noneβ no flags specified.
The default is none.
Besides the = operator, this option also supports += and -= to add/remove flags instead of replacing them π
Important bestie π«Ά the default of associating windows with the spawn workspace and thexterm_fontadjflag both rely onlibswmhack.so. See the βSWMHACKβ section below for more.
spawn_positionβ where in the stack newly spawned windows get placed π possible values arefirst,next,previousandlast(default).nextandpreviousare relative to the focused window.stack_enabledβ enable or disable displaying the current stacking algorithm in the status bar πstack_mark_floatingβ sets the floating layout mark for thebar_formatstacking indicator (+S). Default is'[~]'.stack_mark_horizontalβ sets the horizontal layout mark for thebar_formatstacking indicator (+S). Default is'[-]'.stack_mark_horizontal_centerβ sets thehorizontal_centerlayout mark for thebar_formatstacking indicator (+S). Default is'(-)'.stack_mark_horizontal_center_flipβ sets thehorizontal_center_fliplayout mark for thebar_formatstacking indicator (+S). Default is'(v)'.stack_mark_horizontal_flipβ sets thehorizontal_fliplayout mark for thebar_formatstacking indicator (+S). Default is'[v]'.stack_mark_maxβ sets themaxlayout mark for thebar_formatstacking indicator (+S). Default is'[ ]'.stack_mark_verticalβ sets the vertical layout mark for thebar_formatstacking indicator (+S). Default is'[|]'.stack_mark_vertical_centerβ sets thevertical_centerlayout mark for thebar_formatstacking indicator (+S). Default is'(|)'.stack_mark_vertical_center_flipβ sets thevertical_center_fliplayout mark for thebar_formatstacking indicator (+S). Default is'(>)'.stack_mark_vertical_flipβ sets thevertical_fliplayout mark for thebar_formatstacking indicator (+S). Default is'[>]'.term_widthβ sets a preferred minimum width for the terminal π₯οΈ if this value is greater than0, spectrwm will attempt to adjust the font sizes in the terminal to keep the terminal width above that number as the window is resized β¨
β¦and yes, this next bit is still under that same option, so like, stay with me bestie π
Heads up: onlyxterm(1)is supported rn. The terminal process has to be spawned with thexterm_fontadjspawn flag, and theXTERM_FONTADJquirk has to be set on its window β check thespawn_flagsoption and the βQUIRKSβ section if you're lost. ALSO, thexterm(1)binary must not be setuid or setgid, which (annoyingly) it is by default on most systems π. You might need to setprogram[term](peep the βPROGRAMSβ section) to use a different copy of thexterm(1)binary that doesn't have the setgid bit set. Slay.
uniconify_orderβ sets the window order in the uniconify menu. The possible values areearliest,latest, andworkspace(that's the default, btw).tile_gapβ pixel width of the empty space between tiled windows. Negative values make them overlap (chaotic, love that). Set it to the opposite ofborder_widthto collapse the border between tiles. Want it off? Set it to0.urgent_collapseβ shrinks the space the urgency hint indicator eats up by removing the placeholders for non-urgent workspaces, the trailing space when there are urgent windows, and the default leading space. Turn it on by setting it to1.urgent_enabledβ turns the urgency hint indicator in the status bar on or off. Ngl, many terminal emulators need an explicit setting for the bell character before it'll trigger urgency on the window. Inxterm(1), for example, you gotta add this line to.Xdefaults:
xterm.bellIsUrgent: true
verbose_layoutβ turns displaying the current master window count and stack column/row count in the status bar on or off. Set it to1to enable. Seemaster_add,master_del,stack_incandstack_decfor more info.warp_focusβ focuses on the target window/workspace/region when clamped. For example, when you try to switch to a workspace that's mapped on another region andworkspace_clampis enabled, it focuses on the region with the target workspace. Set it to1to enable.warp_pointerβ centers the pointer on the focused window whenever you use bindings to change focus, switch workspaces, change regions, etc. Set it to1to enable. β οΈ Heads up: this option is ignored whenfocus_modeis set tofollow.window_class_enabledβ turns displaying the window class name (fromWM_CLASS) in the status bar on or off. Set it to1to enable.window_instance_enabledβ turns displaying the window instance name (fromWM_CLASS) in the status bar on or off. Set it to1to enable.window_name_enabledβ turns displaying the window display name (from_NET_WM_NAME/WM_NAME) in the status bar on or off. Set it to1to enable.
To stop excessively large window names from pushing the rest of the text off the bar, it's limited to 64 characters by default. See the bar_format option for more deets.
workspace_autorotateβ when moving workspaces across regions, auto-rotates vertical/horizontal layouts based on rotation data fromxrandr(1). Set it to1to enable.workspace_clampβ prevents workspaces from being swapped when you try to switch to a workspace that's mapped to another region. Usewarp_focusif you want to focus on the region containing the workspace, andwarp_pointerif you also want to send the pointer there. Set it to1to enable.workspace_indicatorβ configures the status bar workspace indicator. You can specify one or more of these options in a comma-separated list:listcurrentβ include the current workspace.listactiveβ include workspaces with windows.listemptyβ include empty workspaces.listnamedβ include named workspaces.listurgentβ include workspaces with urgent window(s).listallβ include all workspaces.hidecurrentβ always exclude the current workspace from the list.markcurrentβ indicate the current workspace if it's in the list.markactiveβ indicate workspaces in the list that are active.markemptyβ indicate workspaces in the list that are empty.markurgentβ indicate workspaces in the list that contain urgent window(s).printnamesβ display the names of named workspaces in the list.noindexesβ hide the index of the workspaces.
The default is listcurrent,listactive,markcurrent,printnames.
π Note that markup sequences can be used to style the workspace indicator. For example, to change the color of the current workspace:
workspace_mark_current = '+@fg=1;'
workspace_mark_current_suffix = '+@fg=0;'
workspace_limitβ sets the total number of workspaces available. Minimum is1, maximum is100, default is10. Note that workspaces23and above don't have default bindings. See the βBINDINGSβ section below for defaults and customization. To limit the workspaces listed in the bar, seebar_workspace_limit.workspace_mark_activeβ sets the string inserted before active workspaces in theworkspace_indicator. Default is'^'.workspace_mark_active_suffixβ sets the string inserted after active workspaces in theworkspace_indicator. Default is''(empty string).workspace_mark_currentβ sets the string inserted before the current workspace in theworkspace_indicator. Default is'*'.workspace_mark_current_suffixβ sets the string inserted after the current workspace in theworkspace_indicator. Default is''(empty string).workspace_mark_emptyβ sets the string inserted before empty workspaces in theworkspace_indicator. Default is'-'.workspace_mark_empty_suffixβ sets the string inserted after empty workspaces in theworkspace_indicator. Default is''(empty string).workspace_mark_urgentβ sets the string inserted before urgent workspaces in theworkspace_indicator. Default is'!'.workspace_mark_urgent_suffixβ sets the string inserted after urgent workspaces in theworkspace_indicator. Default is''(empty string).
π¦ STACK MODES π¦
Okay so this is the layout tea, bestie β how your windows get stacked, literally:
verticalβ master area is on the left, stack area is on the right. Additional windows are vertically tiled in the stack area.vertical flippedβ same as above but the stack and master areas are swapped.horizontalβ master area is on the top, stack area is on the bottom. Additional windows are horizontally tiled in the stack area.horizontal flippedβ same as above but the stack and master areas are swapped.maxβ the focused window occupies the whole region, except for the bar (if it's enabled).floatingβ windows are untiled and can be resized and positioned. Free spirits fr fr.
π WINDOW STATES π
These can be set/unset by the corresponding toggle actions listed in the βBINDINGSβ section below. Periodt.
floatingβ the window is stacked above others and isn't in a tile; it may be freely resized and positioned.belowβ the window is floating, but stacked below others. Humble king energy.maximizedβ the window occupies the work area of the region (the area that excludes space reserved by the bar, docks/panels, etc.). By default, focusing another window removes the maximized state of the window. Seemaximized_unfocusto configure the unfocused behavior.fullscreenβ the window occupies the whole region. By default, focusing another window does not remove the fullscreen state of the window. Seefullscreen_unfocusto configure the unfocused behavior.freeβ the window is floating, but not bound by regions, workspaces or their layouts. It's always mapped (unless iconified) and may be resized and positioned anywhere. Main character energy, honestly π .
π» PROGRAMS π»
okay so this is where spectrwm lets you make your own actions that launch whatever programs you want, and then bind them exactly like the built-in ones. periodt. see the BINDINGS section below (you literally cannot miss it).
custom programs in the config file go like this:
program[action] = progpath [arg [arg ...]]
where action is any identifier that doesn't collide with a built-in action or keyword, progpath is the program you actually want, and arg is zero or more arguments to hand it. zero! or more! your call bestie β¨
with the exception of ~ expansion, program calls are executed as-is, no interpretation whatsoever. if you need shell stuff, call a shell to do it, like sh -c 'command string'. iykyk π
β οΈ real talk: when you use#in your program call, it must be escaped with a backslash, i.e.\#. do not forget or the config will simply Not.
the following argument variables get swapped out for actual values at the exact moment the program is spawned:
$bar_border$bar_color$bar_color_selected$bar_font$bar_font_color$bar_font_color_selected$color_focus$color_unfocus$color_urgent$dmenu_bottomβ becomes-bifbar_at_bottomis enabled, otherwise''(empty string, the void, nothing)$region_index$workspace_index
example, because we love a demo:
program[ff] = /usr/local/bin/firefox http://spectrwm.org/
bind[ff] = MOD+Shift+b # Now M-S-b launches firefox
and to cancel the previous one, you unbind it:
bind[] = MOD+Shift+b
slay, undone π
a bunch of built-in actions spawn a program as part of their implementation, and their respective default program entries are literally these:
termβxtermlockβxlockmenuβdmenu_run $dmenu_bottom -fn $bar_font -nb $bar_color -nf $bar_font_color -sb $bar_color_selected -sf $bar_font_color_selectedsearchβdmenu $dmenu_bottom -i -fn $bar_font -nb $bar_color -nf $bar_font_color -sb $bar_color_selected -sf $bar_font_color_selectedname_workspaceβdmenu $dmenu_bottom -p Workspace -fn $bar_font -nb $bar_color -nf $bar_font_color -sb $bar_color_selected -sf $bar_font_color_selectedinitscrβinitscreen.sh# optionalscreenshot_allβscreenshot.sh full# optionalscreenshot_windβscreenshot.sh window# optional
note note note: search is required by the search_win, search_workspace, and uniconify actions, and it does not have a direct binding. she's booked and busy behind the scenes π
with the exception of the default entries marked optional, validation is performed to make sure the program actually exists. and if validation fails? you've got options, bestie:
- install the program, or
- add the
optionalflag to the program entry's spawn flags, or - disable the program entry by freeing the respective binding
for example, to add the optional flag to lock:
spawn_flags[lock] += optional
and to unbind lock and stop it from being validated at all:
bind[] = MOD+Shift+Delete
πΈ also important: when a program is spawned, spectrwm aims to place its windows in its spawn workspace. if a program fails to spawn in the correct workspace, see the SWMHACK section below for more info, tips, and workarounds. it's giving "we tried our best" π
β¨οΈ BINDINGS β¨οΈ
spectrwm gives you a whole menu of functions (or actions) that you access via key or pointer button bindings. iconic behavior fr fr.
the default bindings are listed below β go off π
β¨Button1β©β focusM-β¨Button1β©β moveM-β¨Button3β©β resizeM-S-β¨Button3β©β resize_centeredM-S-β¨Returnβ©β termM-pβ menuM-S-qβ quitM-qβ restartβ¨unboundβ©β restart_of_dayβ¨unboundβ©β reloadM-β¨Spaceβ©β cycle_layoutM-\β center_layoutM-S-\β flip_layoutβ¨unboundβ©β prior_layoutβ¨unboundβ©β layout_verticalβ¨unboundβ©β layout_horizontalβ¨unboundβ©β layout_maxβ¨unboundβ©β layout_floatingM-S-β¨Spaceβ©β stack_resetβ¨unboundβ©β stack_balanceM-hβ master_shrinkM-lβ master_growM-,β master_addM-.β master_delM-S-,β stack_incM-S-.β stack_decM-β¨Returnβ©β swap_mainM-j,M-β¨TABβ©β focus_nextM-k,M-S-β¨TABβ©β focus_prevM-mβ focus_mainM-`β focus_freeM-S-aβ focus_priorM-uβ focus_urgentM-S-jβ swap_nextM-S-kβ swap_prevM-bβ bar_toggleM-S-bβ bar_toggle_wsM-xβ wind_delM-S-xβ wind_killM-β¨1-9,0,F1-F12β©β ws_β¨1-22β©β¨unboundβ©β ws_β¨23-100β©M-S-β¨1-9,0,F1-F12β©β mvws_β¨1-22β©β¨unboundβ©β mvws_β¨23-100β©M-β¨Keypad 1-9β©β rg_β¨1-9β©M-S-β¨Keypad 1-9β©β mvrg_β¨1-9β©β¨unboundβ©β mvrg_nextβ¨unboundβ©β mvrg_prevβ¨unboundβ©β ws_emptyβ¨unboundβ©β ws_empty_moveM-β¨Rightβ©β ws_nextM-β¨Leftβ©β ws_prevM-β¨Upβ©β ws_next_allM-β¨Downβ©β ws_prev_allM-aβ ws_priorM-S-β¨Downβ©β ws_prev_moveM-S-β¨Upβ©β ws_next_moveM-S-β¨Rightβ©β rg_nextM-S-β¨Leftβ©β rg_prevβ¨unboundβ©β rg_move_nextβ¨unboundβ©β rg_move_prevM-sβ screenshot_allM-S-sβ screenshot_windM-S-vβ versionM-tβ float_toggleM-S-tβ below_toggleM-S-`β free_toggleM-S-β¨Deleteβ©β lockM-S-iβ initscrM-wβ iconifyM-S-wβ uniconifyβ¨unboundβ©β uniconify_quickM-eβ maximize_toggleM-S-eβ fullscreen_toggleM-rβ raiseM-S-rβ always_raiseM-vβ button2M--β width_shrinkM-=β width_growM-S--β height_shrinkM-S-=β height_growM-[β move_leftM-]β move_rightM-S-[β move_upM-S-]β move_downM-S-/β name_workspaceM-/β search_workspaceM-fβ search_winM-dβ debug_toggle (debug mode only)M-S-dβ dumpwins (debug mode only)
the action names and descriptions are listed below:
focusβ focuses the window/region under the pointer β¨moveβ drags the window around with the pointer for as long as you're holding the binding downresizeβ resizes the window with the pointer while the binding is heldresize_centeredβ same whole vibe asresize, but the window stays centered πtermβ spawns a new terminal (peep βPROGRAMSβ above)menuβ pops the menu (again, peep βPROGRAMSβ above)quitβ bye-bye spectrwm πrestartβ restarts spectrwmrestart_of_dayβ same asrestartexcept the config file gets loaded in full, minus autorunreloadβ reloads the config without restarting, and reinitializes the bar(s) plusbar_action(if you use it)cycle_layoutβ hops to the next layoutcenter_layoutβ toggles centering of the master areaflip_layoutβ swaps the master and stacking areasprior_layoutβ back to the last layout you usedlayout_verticalβ switches to vertical layoutlayout_horizontalβ switches to horizontal layoutlayout_maxβ switches to max layoutlayout_floatingβ switches to floating layoutstack_resetβ resets the layoutstack_balanceβ balances the master/stacking area βοΈmaster_shrinkβ shrinks the master areamaster_growβ grows the master areamaster_addβ adds windows to the master areamaster_delβ removes windows from the master areastack_incβ adds columns/rows to the stacking areastack_decβ removes columns/rows from the stacking areaswap_mainβ sends the current window to the master areafocus_nextβ focuses the next window in the workspacefocus_prevβ focuses the previous window in the workspacefocus_mainβ focuses the main window in the workspacefocus_priorβ focuses the window you focused last in the workspacefocus_freeβ focuses a window in free mode, if there even is onefocus_urgentβ focuses the next window with the urgency hint flag set π the workspace switches if it has toswap_nextβ swaps with the next window in the workspaceswap_prevβ swaps with the previous window in the workspacebar_toggleβ toggles overall visibility of the status barsbar_toggle_wsβ toggles the status bar on the current workspacewind_delβ deletes the current windowwind_killβ kills the program that created the current window πws_nβ switches to workspace n, where n is at least 1mvws_nβ moves the current window to workspace n, where n is at least 1rg_nβ focuses region n, where n is at least 1mvrg_nβ moves the current window to region n, where n is at least 1mvrg_nextβ moves the current window to the workspace in the next regionmvrg_prevβ moves the current window to the workspace in the previous regionws_emptyβ switches to the first empty workspacews_empty_moveβ switches to the first empty workspace and moves the current window therews_nextβ switches to the next workspace that actually has a window in itws_prevβ switches to the previous workspace that has a window in itws_next_allβ switches to the next workspace, periodws_prev_allβ switches to the previous workspace, periodws_next_moveβ switches to the next workspace, taking the current window with youws_prev_moveβ switches to the previous workspace, taking the current window with youws_priorβ back to the last workspace you visitedrg_nextβ switches to the next regionrg_prevβ switches to the previous regionrg_move_nextβ goes to the next region and moves the current workspace thererg_move_prevβ goes to the previous region and moves the current workspace therescreenshot_allβ screenshots the entire screen (if enabled) (see βPROGRAMSβ above) πΈscreenshot_windβ screenshots the selected window (if enabled) (see βPROGRAMSβ above)versionβ toggles the version display in the status barfloat_toggleβ toggles the focused window between tiled and floatingbelow_toggleβ toggles the below state on the current windowfree_toggleβ toggles the focused window between workspace mode and free modelockβ locks the screen (see βPROGRAMSβ above) πinitscrβ reinitializes the physical screens (see βPROGRAMSβ above)iconifyβ minimizes (unmaps) the currently focused windowuniconifyβ restores (maps) the window returned by yourdmenu(1)selectionuniconify_quickβ restores (maps) the window you iconified most recentlymaximize_toggleβ toggles maximization of the focused windowfullscreen_toggleβ toggles fullscreen state of the focused windowraiseβ raises the current windowalways_raiseβ when this is set, tiled windows are allowed to obscure floating windowsbutton2β fakes a middle mouse button click (Button2)width_shrinkβ shrinks the width of a floating windowwidth_growβ grows the width of a floating windowheight_shrinkβ shrinks the height of a floating windowheight_growβ grows the height of a floating windowmove_leftβ moves a floating window one step to the leftmove_rightβ moves a floating window one step to the rightmove_upβ moves a floating window one step upwardsmove_downβ moves a floating window one step downwardsname_workspaceβ names the current workspacesearch_workspaceβ searches for a workspacesearch_winβ searches the windows in the current workspacedebug_toggleβ toggles the debug overlay (debug mode only) πdumpwinsβ dumps the current window/focus/stacking state to the debug log (debug mode only)
π οΈ your own custom bindings, bestie
Custom bindings in the config file go like this:
bind[action] = combo
action is literally one of the actions listed above (or leave it empty to unbind something), and combo is zero or more modifier keys and/or special arguments (Mod1, Shift, Control, MOD, etc.) followed by a normal key (b, Space, etc.) or a button (Button1 .. Button255), all held together with +. And yes β multiple key/button combos can be bound to the same action, no cap π
the special arguments, iconically
MODβ gets substituted for the currently defined modkeyANYMODβ selects all modifier combinations that aren't handled by another bindingREPLAYβ reprocesses binding press/release events so other programs can handle them too. Unavailable formove,resizeandresize_centeredπ«Ά
MOD example
bind[reset] = Mod4+q # bind Windows-key + q to reset
bind[] = Mod1+q # unbind Alt + q
bind[move] = MOD+Button3 # Bind move to M-Button3
bind[] = MOD+Button1 # Unbind default move binding.
ANYMOD example
bind[focus] = ANYMOD+Button3
bind[move] = MOD+Button3
In the example above, M+Button3 kicks off move, and Button3 pressed with literally any other combination of modifiers sets focus to the window/region under the pointer β¨
REPLAY example
bind[focus] = REPLAY+Button3
In this one, when Button3 is pressed without any modifier(s), focus gets set to the window under the pointer and the button press gets passed through to the window π«Ά
So here's the tea on non-latin characters: if you wanna bind something like Γ₯ or Ο, you have to type the xkb character name instead of the character itself. Run xev(1), focus the window, press that specific key, and read the symbol name in the terminal output. Here's the example for Γ₯:
KeyPress event, serial 41, synthetic NO, window 0x2600001,
root 0x15a, subw 0x0, time 106213808, (11,5), root:(359,823),
state 0x0, keycode 24 (keysym 0xe5, aring), same_screen YES,
XLookupString gives 2 bytes: (c3 a5) "Γ₯"
XmbLookupString gives 2 bytes: (c3 a5) "Γ₯"
XFilterEvent returns: False
See how the xkb name is aring? So in other words, in spectrwm.conf you'd add:
bind[program] = MOD+aring
And if you wanna clear out all the default keyboard bindings and roll with only your own, go look at the keyboard_mapping option π
β¨οΈ KEYBOARD MAPPING FILES β¨οΈ
Okay so listen β there are keyboard mapping files for a bunch of keyboard layouts, and they're listed right here. You use them with the keyboard_mapping setting to load pre-defined key bindings for whichever layout you've got π
spectrwm_cz.confβ Czech Republic keyboard layoutspectrwm_es.confβ Spanish keyboard layoutspectrwm_fr.confβ French keyboard layoutspectrwm_fr_ch.confβ Swiss French keyboard layoutspectrwm_se.confβ Swedish keyboard layoutspectrwm_us.confβ United States keyboard layout
β¨ QUIRKS β¨
Okay so spectrwm has a whole quirks system, and itβs genuinely iconic for handling windows that need special treatment in a tiling window manager β think certain dialogs and fullscreen apps. Itβs giving βmain character windows get their own rules,β and honestly? Slay. π
Here are the default quirks, no cap:
.*:.*:.*:splash,dialog FLOAT
.*:.*:.*:toolbar,utility FLOAT + ANYWHERE
.*:.*:.*:notification FLOAT + ANYWHERE +
MINIMALBORDER +
NOFOCUSONMAP
Firefox-bin:firefox-bin TRANSSZ
Firefox:Dialog FLOAT
Gimp:gimp FLOAT + ANYWHERE
MPlayer:xv FLOAT + FULLSCREEN +
FOCUSPREV
OpenOffice.org 2.4:VCLSalFrame FLOAT
OpenOffice.org 3.1:VCLSalFrame FLOAT
pcb:pcb FLOAT
xine:Xine Window FLOAT + ANYWHERE
xine:xine Panel FLOAT + ANYWHERE
xine:xine Video Fullscreen Window FULLSCREEN + FLOAT
Xitk:Xitk Combo FLOAT + ANYWHERE
Xitk:Xine Window FLOAT + ANYWHERE
XTerm:xterm XTERM_FONTADJ
π The Quirks Themselves π
Now the quirks themselves, one by one, bestie:
ANYWHEREβ lets the window position itself, uncentered. Itβs giving βI know where I belong.β β¨BELOWβ puts the window into below state as soon as it gets managed.FLOATβ this window should not be tiled; let it float freely, like the free spirit it is. π¦FOCUSONMAP_SINGLEβ when the window first appears on the screen, change focus to it if there are no other windows on the workspace with the sameWM_CLASSclass/instance value. Has no effect whenfocus_modeis set tofollow.FOCUSPREVβ on exit, force focus on the previously focused application, not the previous application in the stack.FULLSCREENβ removes the border so the window can use the full region size. Big βedge-to-edgeβ energy.ICONIFYβ hides/minimizes the window upon being managed.IGNOREPIDβ ignores the PID when determining the initial workspace for a new window. Especially useful for terminal windows that share a process.IGNORESPAWNWSβ ignores the spawn workspace when determining the initial workspace for a new window.IGNOREURGENTβ ignores the urgency hint. Not today, urgency.MAXIMIZEβ puts the window into maximized state upon being managed.MINIMALBORDERβ removes the border when the window is unfocused and floating.NOFOCUSCYCLEβ removes the window from the normal focus cycle (focus_prevorfocus_next). It can still be focused usingsearch_win.NOFOCUSONMAPβ do not change focus to the window when it first appears on the screen. Has no effect whenfocus_modeis set tofollow.NOFOCUSPOINTERβ do not focus the window via pointer interaction. It can still be focused using key bindings.OBEYAPPFOCUSREQβ when an application requests focus on the window via a_NET_ACTIVE_WINDOWclient message (source indication of 1), comply with the request. Note that a source indication of 0 (unspecified) or 2 (pager) are always obeyed.TRANSSZβ adjusts size on transient windows that are too small usingdialog_ratio(see βCONFIGURATION FILESβ).WS[n]β forces a new window to appear on workspacen. Specify-1to put the window into free mode so that it is mapped independent of workspaces and regions.XTERM_FONTADJβ adjustsxterm(1)fonts when resizing. Note that this requires thexterm_fontadjspawn flag to be set on theautorun/programentry when the program is spawned. See thespawn_flagsoption for info on how to enable it.NOTILEβ disallows the window from being tiled. Note that the window will always float regardless of whether_NET_WM_STATE_ABOVEis set.
Custom Quirks, Bestie π
Custom quirks in the configuration file are specified as follows:
quirk[class[:instance[:name[:type]]]] {=|+=|-=} quirk [+ quirk
...]
class, instance (optional), name (optional), and type (optional) are used to determine which window(s) the quirk(s) apply to. class and instance are regex search patterns for the respective fields of the WM_CLASS window property. name is a regex search pattern for the window name (WM_NAME/_NET_WM_NAME.) type is a comma-separated list of zero or more of the following window types (_NET_WM_WINDOW_TYPE): desktop, dock, toolbar, menu, utility, splash, dialog, dropdown_menu, popup_menu, tooltip, notification, combo, dnd, and normal. Leave this field blank to match any window type. quirk is one of the quirks from the list above.
When a window is managed, quirk entries are applied in the order specified in the configuration file. The assignment operator determines how the quirks are applied. When assigning quirks with =, quirks are replaced on matching windows. To add or remove quirks, assign them with += or -= instead.
Note that patterns are interpreted as POSIX Extended Regular Expressions. Any':','['or']'must be escaped with'\'. Seeregex(7)for more information on POSIX Extended Regular Expressions.
For example:
quirk[MPlayer] = FLOAT + FULLSCREEN + FOCUSPREV # Float all windows having a class of 'MPlayer'
quirk[.*] = FLOAT # Float all windows by default.
quirk[.*:.*:.*] = FLOAT # Same as above.
quirk[firefox:Navigator] = FLOAT # Float all Firefox browser windows.
quirk[::Console] = FLOAT # Float windows with WM_CLASS not set and a window name of 'Console'.
quirk[\[0-9\].*:.*:\[\[\:alnum\:\]\]*] = FLOAT # Float windows with WM_CLASS class beginning with a number, any WM_CLASS instance and a _NET_WM_NAME/WM_NAME either blank or containing alphanumeric characters without spaces.
quirk[pcb:pcb] = NONE # Remove the default quirk entry.
quirk[.*:ws10] += WS[10] # Force windows with a WM_CLASS name of 'ws10' to workspace 10 without removing existing quirks.
quirk[.*:.*:.*:splash,dialog] = FLOAT + ANYWHERE # Override default quirk entry.
You can obtain class, instance and name by running xprop(1) and then clicking on the desired window. In the following example the main window of Firefox was clicked:
$ xprop | grep -E "^(WM_CLASS|_NET_WM_NAME|WM_NAME)"
WM_CLASS(STRING) = "Navigator", "Firefox"
WM_NAME(STRING) = "spectrwm - ConformalOpenSource"
_NET_WM_NAME(UTF8_STRING) = "spectrwm - ConformalOpenSource"
Note that xprop(1) displays WM_CLASS as:
WM_CLASS(STRING) = "<instance>", "<class>"
In the example above the quirk entry would be:
quirk[Firefox:Navigator] = FLOAT
spectrwm also automatically assigns quirks to windows based on the value of the windowβs _NET_WM_WINDOW_TYPE property as follows:
_NET_WM_WINDOW_TYPE_TOOLBAR FLOAT + ANYWHERE
_NET_WM_WINDOW_TYPE_UTILITY FLOAT + ANYWHERE
_NET_WM_WINDOW_TYPE_SPLASH FLOAT
_NET_WM_WINDOW_TYPE_DIALOG FLOAT
In all other cases, no automatic quirks are assigned to the window. Quirks specified in the configuration file override the automatic quirks. Periodt. π β¨
π EWMH π
okay so spectrwm partially implements the Extended Window Manager Hints (EWMH) specification, and that's literally how external scripts and programs can control windows and spectrwm itself. How? spectrwm responds to certain ClientMessage events. From the terminal you can send these events conveniently with tools like wmctrl(1) and xdotool(1). For the actual format of these ClientMessage events, check the EWMH specification π
The id of the currently focused window is stored in the _NET_ACTIVE_WINDOW property of the root window. This can be used, for example, to retrieve the title of the currently active window with xprop(1) and grep(1):
$ WINDOWID=`xprop -root _NET_ACTIVE_WINDOW | grep -o "0x.*"`
$ xprop -id $WINDOWID _NET_WM_NAME | grep -o "\".*\""
A window can be focused by sending a _NET_ACTIVE_WINDOW client message to the root window. For example, using wmctrl(1) to send the message (assuming 0x4a0000b is the id of the window to be focused):
$ wmctrl -i -a 0x4a0000b
Windows can be closed by sending a _NET_CLOSE_WINDOW client message to the root window. For example, using wmctrl(1) to send the message (assuming 0x4a0000b is the id of the window to be closed):
$ wmctrl -i -c 0x4a0000b
Windows can be floated and un-floated by adding or removing the _NET_WM_STATE_ABOVE atom from the _NET_WM_STATE property of the window. This can be achieved by sending a _NET_WM_STATE client message to the root window. For example, the following toggles the floating state of a window using wmctrl(1) to send the message (assuming 0x4a0000b is the id of the window to be floated or un-floated):
$ wmctrl -i -r 0x4a0000b -b toggle,above
Windows can also be iconified and un-iconified by substituting _NET_WM_STATE_HIDDEN for _NET_WM_STATE_ABOVE in the previous example:
$ wmctrl -i -r 0x4a0000b -b toggle,hidden
Floating windows can also be resized and moved by sending a _NET_MOVERESIZE_WINDOW client message to the root window. For example, using wmctrl(1) to send the message (assuming 0x4a0000b is the id of the window to be resize/moved):
$ wmctrl -i -r 0x4a0000b -e 0,100,50,640,480
This moves the window to (100,50) and resizes it to 640x480.
π«Ά bestie, important caveat: if a window has been manually positioned via binding,_NET_MOVERESIZE_WINDOWrequests are ignored unless the window has theANYWHEREquirk, the workspace is in floating layout, or the window is workspace-free. Requests are also ignored on maximized and fullscreen windows. no cap.
π§ SWMHACK π§
When spawning a program via an autorun or program entry without the nospawnws flag, spectrwm aims to place the program's windows (if any) in its spawn workspace. To accomplish this "spawn-in-workspace" behavior, spectrwm must determine the intended spawn workspace when managing a new window. Since it cannot be done with X11 alone, libswmhack.so is included to make this feature possible β¨
When a program is spawned, spectrwm automatically sets LD_PRELOAD and _SWM_WS in the program's spawn environment to enable libswmhack.so when it is executed. Note that LD_PRELOAD is the path to libswmhack.so and _SWM_WS is the spawn workspace for any windows created by the program.
When running programs from terminals, scripts, etc, the inherited environment may need to be configured. It is possible to override the spawn workspace by setting _SWM_WS to a different value. Alternatively, _SWM_WS can be unset(1) or set to a blank value to disable "spawn-in-workspace" behavior. Note that workspaces are counted from 0. β-1β can be specified to put windows into workspace-free mode.
For example, to play a video with mpv(1) on workspace 10 without changing the spawn workspace in the environment:
$ _SWM_WS=9 mpv video.mkv
Play the video in free mode so that it remains mapped when switching workspaces.
$ _SWM_WS=-1 mpv video.mkv
Disable "spawn-in-workspace" in the environment so that new windows map on whichever workspace happens to be focused.
$ unset _SWM_WS
Change the environment to spawn programs in free mode.
$ export _SWM_WS=-1
When spawning a program that creates windows via a daemon, ensure the daemon is started with the correct LD_PRELOAD in its environment.
For example, when starting urxvtd(1) via xinit(1), LD_PRELOAD must be specified.
LD_PRELOAD=/usr/lib/libswmhack.so.0.0 urxvtd -q -o -f
π note that some operating systems may ignoreLD_PRELOADif certain conditions are not met. It is advised to check the man page ofld.so.
In situations where libswmhack.so cannot be used, it is possible to use a quirk to spawn a program in a specific workspace.
e.g. launch an xterm(1) in workspace 2 on startup:
quirk[XTerm:ws2] += WS[2]
autorun = ws[2]:xterm -name ws2
Launch a chromium(1) window in workspace 3 on startup:
quirk[Chromium:chromium:ws3] += WS[3]
autorun = ws[3]:chromium --window-name="ws3" --new-window
If the "spawn-in-workspace" behavior is not desired, it is possible to disable it before programs are spawned by setting the nospawnws spawn flag on spawn entries via the spawn_flags option:
# Make 'nospawnws' the default for any autorun/program entries that are
# added/replaced below this line in the configuration file:
spawn_flags = nospawnws
program[pcmanfm] = pcmanfm -n # 'nospawnws' is set
autorun = ws[1]:firefox # ws[1] is ignored since 'nospawnws' is set
program[lock] = xlock # the replaced default entry has 'nospawnws' set
# Add 'nospawnws' to an existing entry:
spawn_flags[term] += nospawnws
Alternatively, the IGNORESPAWNWS and IGNOREPID quirks can be applied to windows:
# Disable spawn-in-workspace on PCManFM windows:
quirk[Pcmanfm] = IGNORESPAWNWS
# Disable spawn-in-workspace on all windows, including those spawned via autorun:
quirk[.*] += IGNORESPAWNWS + IGNOREPID
π also: XCB programs that roll their own X11 requests (e.g. Chromium) are currently unsupported by libswmhack.so.
π¨ SIGNALS π¨
Sending spectrwm a HUP signal will restart it. USR1 will reload the configuration without restarting and reinitialize the bar(s) along with bar_action (if used). slay, low-effort reload energy π
π FILES π
~/.spectrwm.confβ spectrwm user specific settings./etc/spectrwm.confβ spectrwm global settings.
πΈ HISTORY πΈ
spectrwm was inspired by xmonad & dwm. iconic lineage tbh π«Ά
π AUTHORS π
spectrwm was written by:
Marco Peereboom β¨marco@peereboom.usβ©Ryan Thomas McBride β¨mcbride@countersiege.comβ©Darrin Chandler β¨dwchandler@stilyagin.comβ©Pierre-Yves Ritschard β¨pyr@spootnik.orgβ©Tuukka Kataja β¨stuge@xor.fiβ©Jason L. Wright β¨jason@thought.netβ©Reginald Kennedy β¨rk@rejii.comβ©Lawrence Teo β¨lteo@lteo.netβ©Tiago Cunha β¨tcunha@gmx.comβ©David Hill β¨dhill@mindcry.orgβ©
okay bestie, that's the whole page β source/version: Debian, dated August 26, 2025, and yeah, SPECTRWM(1) stays main character energy π
β¨π
π¦ where this page comes from
- alpine 3.24: spectrwm-doc 3.7.0-r1 Β· ISC
- nixos 26.05: spectrwm 3.7.0
- nixpkgs unstable: spectrwm 3.7.0
- Copyright (c) 2009-2012 Marco Peereboom <marco@peereboom.us>
- Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
- Copyright (c) 2011-2025 Reginald Kennedy <rk@rejii.com>
- Copyright (c) 2011-2012 Lawrence Teo <lteo@lteo.net>
- Copyright (c) 2011-2012 Tiago Cunha <tcunha@gmx.com>
- Copyright (c) 2012 David Hill <dhill@mindcry.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms