A list based tiling window manager in the vein of dwm, bspwm, and xmonad.
Some basics:
- Heavily scriptable and tinker friendly.
- Dynamic workspaces, any workspace on any monitor.
- More dynamic tile layout with multiple stacks and window resizing.
- Gaps, double borders, additional layouts, padding and more.
- Better support for mouse and floating windows, resize tiles with mouse.
- Startup script for configuration and running programs.
- Status info can be output to a file or piped for use in bars or scripts.
- No built-in extras (bar, font drawing, or key bindings).
- Sane support for icccm, ewmh, and motif.
You need the xcb headers
Arch
xcb-proto xcb-util xcb-util-wm xcb-util-cursor xcb-util-keysyms
Void
libxcb-devel xcb-proto xcb-util-devel xcb-util-wm-devel xcb-util-cursor-devel xcb-util-keysyms-devel
Debian/Ubuntu
libxcb-randr0-dev libxcb-util-dev libxcb-icccm4-dev libxcb-cursor-dev libxcb-keysyms1-dev libxcb-res0-dev
Other systems should have packages with similar names.
To compile run
makeEdit config.h if needed, then run (as root if needed)
make installIf at any time you want to uninstall, run
make uninstallIn order to update dk when built from source you can run
cd dk
git fetch
git reset --hard HEAD
git merge '@{u}'
make
sudo make installAs mentioned above dk has no keybind support so you'll need a program like
sxhkd, xbindkeys, etc. to launch programs and control the window manager.
We'll install sxhkd because the example config uses it.
Arch/Debian/Ubuntu/Void/etc.
sxhkdTo start dk you can add the following to your ~/.xinitrc
exec dkOptionally copy the example dkrc and/or sxhkdrc to ~/.config/dk/
mkdir -p ~/.config/dk
cp /usr/local/share/doc/dk/dkrc ~/.config/dk/
cp /usr/local/share/doc/dk/sxhkdrc ~/.config/dk/There are example dkrc and sxhkdrc files in doc/ or
/usr/local/share/doc/dk after installation.
dk looks for an rc file in the following order
$DKRC # user specified location
$HOME/.config/dk/dkrc # default locationand tries to run it, it must be executable in order for this to happen.
Advanced changes and configuration like new layouts, callbacks, or commands
can be done by copying the default config header config.def.h to config.h,
editing it and recompiling. This file isn't tracked by git so you can keep your
configuration and avoid conflicts when pulling new updates.
Most of your interaction with the window manager will be using dkcmd
which writes one or more commands into the socket where it is then read
and parsed by the window manager (see Commands section below).
dkcmd accepts one flag with an optional file argument
-pPretty format JSON input from passed file or STDIN and print on STDOUT.
dkcmd status type=bar num=1 | dkcmd -p
# or
dkcmd -p output.jsonThe commands have a very basic syntax and parsing, the input is broken
down into smaller pieces (tokens) which are then passed to the matching
keyword function, otherwise an error is returned.
Tokens are delimited by one or more:
-
whitespace (space or tab)
-
quotation mark (
'or") -
equal sign (
=)
This means the following inputs are all equivalent.
setting=value
setting value
setting="value"
setting = 'value'
setting "value"
setting "value"
and result in two tokens: setting and value
Quotation exists as a way to preserve whitespace and avoid interpretation by the shell,
otherwise we have no way of determining whether an argument is a continuation of the
previous or the beginning of the next. Consider the following
title="^open files$"If the value being matched has quotes in it, they can be escaped or strong quoted
title="^\"preserved quotes\"$"
title='^"preserved quotes"$'For various commands dk will expect a certain data type or format to be given.
-
string: normal plain text, must be less than 256 characters.
-
boolean:
true,false,1, or0. -
hex:
(0x/#)XXXXXXXX, used for window ids -
integer:
(+/-)1, if it is preceded by a sign it is considered relative. -
float:
(+/-)0.1, same as integer but must contain a decimal value. -
colour:
(0x/#)[AA]RRGGBB, hex value, if no alpha channel is given the colour is opaque.
dkcmd COMMANDexitexit dk.restartre-execute dk.
mon and ws operate on monitors and workspaces respectively.
CLIENT(hex/string) The window id in hex or class string, if unspecified the active window is used.TARGET(integer/string) Name or number of the workspace or monitor to target or stringsnextrelative forwardprevrelative backwardlastlast viewednextnenext non-emptyprevneprevious non-empty
ws [SUBCOMMAND] [CLIENT] TARGET
mon [SUBCOMMAND] [CLIENT] TARGETview View the TARGET, default if no subcommand is given.
ws view TARGET
ws TARGETsend Send CLIENT to the TARGET.
mon send [CLIENT] TARGETfollow Follow CLIENT to the TARGET.
ws follow [CLIENT] TARGETrule operates on window rules.
MATCHone or more regex strings to be used when matching window properties.SETTINGone or more window setting to be applied when a matched window is encountered.
rule [SUBCOMMAND] MATCH SETTINGapply applies RULE to all matching windows, if RULE is * apply all rules and MATCH is ignored.
rule apply RULE [MATCH]remove removes RULE, if RULE is * remove all rules and MATCH is ignored.
rule remove RULE [MATCH]class instance title type (string) regex to match the window class, instance, title, and
type respectively (may be prefixed with match_ for clarity). Regex matching is always done case insensitive
with extended regex mode enabled.
rule [SUBCOMMAND] class="^firefox$" instance="^navigator$" title="^mozilla firefox$" type=dialog [SETTING]type currently only supports dialog and splash windows, all others are treated as normal windows.
ws (integer/string) determine what workspace the window should be on.
rule MATCH ws=1 # using index
rule MATCH ws=term # using namemon (integer/string) determine what monitor the window should be on.
rule MATCH mon=1 # using index
rule MATCH mon=HDMI-A-0 # using namex y w width h height bw border_width (integer/string) determine the window location and size.
-
xchange the x coordinate, can be an integer or one of the following.center leftandrightgravitate on the x coordinate.
-
ychange the y coordinate, can be an integer or one of the following.center topandbottomgravitate on the y coordinate.
-
wwidthchange the window width. -
hheightchange the window height. -
bwborder_widthchange the window border width.
rule MATCH x=20 y=100 w=1280 h=720 bw=0 # using absolute values
rule MATCH x=center y=center w=1280 h=720 bw=0 # using gravitiescallback (string) determine a callback function to be invoked on window open and close.
These are defined in the config header and compiled into the source, one example is provided.
rule MATCH callback=albumartfloat stick (boolean) determine if the window should be floating or stick respectively.
rule MATCH float=true stick=trueignore_cfg (boolean) determine if the window should ignore configure request
events (size or location changes).
rule MATCH ignore_cfg=trueignore_msg (boolean) determine if the window should ignore client message
window activation events (grabbing focus).
rule MATCH ignore_msg=truefocus (boolean) determine if the window should be focused and view it's workspace.
If mon is also set it will be activated first before viewing the workspace.
rule MATCH focus=trueterminal (boolean) determine if the window should be considered a terminal for
absorbing other windows and not being absorbed itself.
rule MATCH terminal=trueno_absorb (boolean) determine if the window should never absorb other windows.
rule MATCH no_absorb=truescratch (boolean) determine if the window should be in the scratchpad.
rule MATCH scratch=trueset operates on workspace or global configuration settings.
SETTINGone or more settings to be changed.WSthe workspace which subcommand should apply to, if unspecified the current is used.
_is a special workspace used to define default values for new workspaces which
haven't been created yet.
set [WS] SETTING
set ws=_ [apply] SETTINGnumws (integer) change the number of workspaces to allocate.
set numws=10name (string) change the WS name.
set ws=1 name="term"static_ws (boolean) disable dynamic workspaces for multi-head systems.
set static_ws=falsemon (integer/string) change which monitor WS should be on (requires static_ws=true).
set ws=1 mon=HDMI-A-0
set ws=1 mon=1master stack (integer) change the number of windows to occupy the master area (tile layout).
set [WS] stack 3 # absolute values have no signs
set [WS] master +1 stack -1 # relative change with signed integers (+/-)msplit ssplit (float) change the workspace master or stack split ratios respectively.
set [WS] msplit +0.1
set [WS] ssplit 0.55gap (integer) change the workspace gap width.
set [WS] gap 10tile_hints (boolean) obey size hints in tiled layouts.
set tile_hints=truetile_tohead (boolean) place new windows at the head of the list in tiled layouts.
set tile_tohead=truesmart_gap (boolean) whether gaps are disabled on workspaces with only one tiled window.
set smart_gap=truesmart_border (boolean) whether borders are disabled on workspaces with only one tiled window.
set smart_border=truefocus_urgent (boolean) focus windows that request it.
set focus_urgent=truefocus_open (boolean) whether windows are focused when opened.
set focus_open=falsefocus_mouse (boolean) whether window focus follows the mouse.
set focus_mouse=falseobey_motif (boolean) whether to obey motif hints for borders.
set obey_motif=falsewin_minxy (integer) amount of window (in pixels) to be kept on the screen when moving.
set win_minxy=20win_minwh (integer) minimum window size.
set win_minwh=50apply when changing the default _ workspace apply settings to existing real workspaces.
set ws=_ apply SETTINGlayout (string) change the workspace window layout.
tiledefault tile layoutrtiletile layout with master area on the rightmonowindows arranged maximized and stackedgridall windows try to occupy equal spacespiralwindows shrink by 1/2 towards the center of the screendwindlewindows shrink by 1/2 towards the bottom right of the screentstackwindows are grouped into a master area on the bottom and one horizontal stack area on top.nonefloating layout, windows can be freely moved and resized.cycleswitch between available layouts.
set [WS] layout monoborder change the window border sizes and colours.
wwidth(integer) change the overall window border width.owouterouter_width(integer) change the outer border width (greater than 0 makes double borders).colourcolor(string) change the border (overall and outer) colour for various window states.ffocus(colour) the active window border overall colour.rurgent(colour) urgent window border overall colour.uunfocus(colour) normal window border overall colour.ofouter_focus(colour) the active window outer border colour.orouter_urgent(colour) urgent window outer border colour.ououter_unfocus(colour) normal window outer border colour.
set border w=5 ow=3 colour f='#6699cc' u='#444444' r='#ee5555' of='#222222' ou='#222222' or='#222222'pad change the workspace padding.
lleft(integer) change the workspace left side padding.rright(integer) change the workspace right side padding.ttop(integer) change the workspace top padding.bbottom(integer) change the workspace bottom padding.
set [WS] pad l=50 r=50 t=50 b=50mouse change the mouse binds for move and resize (global, does not take a workspace).
-
mod(string) change the modifier used in combination with move resize buttons.altmod1Alt key (default).supermod4Win key.ctrlcontrolCtrl key.
-
moveresize(string) change the button used for move and resize respectively.button1left mouse button.button2right mouse button.button3middle mouse button.
set mouse move=button1 resize=button2 mod=mod1win operates on windows.
CLIENT(hex/string) the window id in hex or class string, if unspecified the current window is used.
win [CLIENT] ACTIONcycle cycle windows in place.
win cyclefloat change the window floating state.
win [CLIENT] float
win [CLIENT] float=falsefull change the window fullscreen state.
win [CLIENT] fullfakefull change the window fake fullscreen state (allow moving, resizing, and tiling when fullscreen).
win [CLIENT] fakefullstick change the window sticky state.
win [CLIENT] stickswap change the window between it's current location and master.
win [CLIENT] swapkill close the window.
win [CLIENT] killfocus (integer/string) change the focused window.
nextfocus the next window.prevfocus the previous window.
win CLIENT focus # focus window by id
win focus next # focus the next window
win focus +2 # focus two windows aheadscratch view or hide a scratchpad window.
popshow a window in the scratch.pushhide a window in the scratch.
With no other arguments
- If there are window(s) in the scratch it will continue to pop them out until empty.
- If there is a window on any workspace (other than the current workspace) that has been recently popped, it will be brought to the current workspace. If it's on the current workspace it is instead pushed.
- If there are no window(s) in the scratch and no windows that have been there previously it will push the active window into the scratch.
win scratch
win [CLIENT] scratch # same toggle behaviour but on the passed window
win [CLIENT] scratch push # push the given window or the active window.mvstack (integer/string) move a tiled window around the stack.
upmove the tiled window up the stack.downmove the tiled window down the stack.
win [CLIENT] mvstack upresize change the window size, location, and border width.
-
xchange the x coordinate, can be an integer or one of the following.center leftandrightgravitate on the x coordinate.
-
ychange the y coordinate, can be an integer or one of the following.center topandbottomgravitate on the y coordinate.
-
wwidthchange the window width. -
hheightchange the window height. -
bwborder_widthchange the window border width.
win [CLIENT] resize x=100 y=100 w=1280 h=720 bw=1
win [CLIENT] resize x=center y=center w=1280 h=720 bw=1status print status information as JSON to a file or stdout.
status [TYPE] [FILE] [NUM]type (string) the type of status info to output and when to trigger.
wsoutput full workspace info - triggers on workspace change.winoutput current window title - triggers on window or title change.layoutoutput current layout name - triggers on layout change.baridentical output towsexcept - triggers on all changes.fulloutput full wm and client state - triggers on all changes.
status type=ws [FILE] [NUM]file (string) the location of the status file.
status file=/tmp/dk.status [TYPE] [NUM]num (integer) the number of times to output, -1 is infinite and default if not specified.
status [TYPE] [FILE] # output forever
status num=1 [TYPE] [FILE] # output once- Simplification and code quality improvement.
- See ISSSUE.md for current problems and possible additions.
grep -n 'TODO' src/*will give some code I'm not happy with.
I'm very open to contributions or ideas, please feel free to email me or open an issue/PR. For myself I have various builds that can help finding issues or provide some insight. These include:
stderr debug output
make debugdebug output and function calls
make fdebugdon't strip debug symbols (for gdb, valgrind, etc.).
make nostripSee the LICENSE file for a list of authors/contributors.
Huge thanks to Kjetil Molteberg (@badkarma) for the logo.
Non contributors that I owe a huge thanks to:
