dwm Keyboard and Mouse Configuration^
When you use a traditional desktop environment, there is some form of settings configuration that includes a set of keyboard shortcuts where you open a modal and run the shortcut and assign it to a particular operation.
Most desktop environments on Linux and FreeBSD also include the functionality to have a shortcut run some arbitrary script or command. This feature is generally unknown or unheard of in the realm of proprietary operating systems where such extended functionality is more rigidly controlled.
Modifier Key^
When you want to send a command to dwm, generally you press a specific key that shifts the keyboard into its modified state. An example of this in other environments would be the Cmd key on macOS.
In the context of dwm, this is defined as the MODKEY macro:
48#define MODKEY Mod1Mask
This sets MODKEY to Alt. This is a very reasonable
place to put a key that you’re liable to press often—right
under your thumb on a US keyboard.
Personally, I prefer Mod4Mask, which maps to the
Super or Windows key, for this purpose, but I have
a number of odd issues due to fragmentation around muscle memory
that stems from my spending weekday hours on a Mac for work
instead of the infinitely preferable Linux-only model that was a
feature of past employment.
Commands^
The commands section of config.h sets up variables for
commands that dwm runs for you. By default, there are two: dmenu
and the terminal.
Terminal Command^
The termcmd variable specifies the default command to run
when the user requests a terminal. For users of window managers,
the preference is often for a number of lightweight terminals
launched ad hoc to suit the particular needs of the moment.
65static const char *termcmd[] = { "st", NULL };
Since Suckless also develops and maintains a terminal
emulator, st this is the default value. You change
this to xfce-terminal, xterm, ghostty, or
whatever terminal emulator suits your preferences.
Helpers^
In addition to the terminal command, the config.h file also
includes helper macros to aid in whatever operations you need to
run as a keyboard shortcut.
Shell Helper^
The SHCMD macro is used in cases where you want to execute a
shell command in the background. It takes a cmd argument and
expands into the array used to call a script through
/bin/sh.
56#define SHCMD(cmd) { \
57 .v = (const char*[]){ \
58 "/bin/sh", "-c", cmd, NULL \
59 } }
A common use case for this macro is when you mean to run a background script.
For example, a good use of the SHCMD macro would be when you
need to a call script to call isync to synchronize your
local maildir with a remote IMAP server, run Notmuch to update
the index, and then report the number of unread messages through
a string passed into the notification daemon.
Tag Helper^
TAGKEYS is a helper macro used to configure tag operations
in the keyboard shortcuts. It’s main purpose is to set several
common keyboard shortcuts through one call to the key and tag
number.
49#define TAGKEYS(KEY,TAG) \
50 { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
51 { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
52 { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
53 { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
So for example, a call to TAGKEYS(XK_1, 1) would expand so
that:
Alt |
1 |
Views tag 1 |
AltCtrl |
1 |
Toggles the view to include tag 1 with the current tag |
Alt Shift |
1 |
Moves the current window to tag 1 |
Alt Shift Ctrl |
1 |
Adds the current window to tag 1 without removing it from the current tag |
Keyboard Shortcuts^
Keyboard shortcuts are specified in the key array. When you
want to add a shortcut to your build, you do so by adding a
Key structure to this array.
62static const Key keys[] = {
63 /* modifier key function argument */
64 { MODKEY, XK_p, spawn, {.v = dmenucmd } },
65 { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
The structure uses the following pattern:
The first entry is set using a bitwise operator that combines the modifier keys needed for the shortcut. The
MODKEYmacro was defined above and defaults to the Alt key. You can then apply theShiftMaskand/orControlMaskto refine the modification.The key specifies the key on the keyboard that you press with the modifier. The
XK_pfor example, corresponds to the p key.The function is the specific C function in the dwm code base that gets called when the user presses the given key with the given modifiers. The
spawn()function, for example, runs an application or script.The arguments refer to the arguments that are passed to the function, such as the argument to launch dmenu or st or the argument to increment a tag.
At the bottom of this array, you’ll see the TAGKEYS() helper
macro in use to define common operations that apply to all tags.
94 TAGKEYS( XK_7, 6)
95 TAGKEYS( XK_8, 7)
96 TAGKEYS( XK_9, 8)
97 { MODKEY|ShiftMask, XK_q, quit, {0} },
98};
Mouse Controls^
The last section in the default config.h covers mouse
controls. This is set on the buttons array. Each item in
this array is a Button structure.
102static const Button buttons[] = {
103 /* click event mask button function argument */
104 { ClkLtSymbol, 0, Button1, setlayout, {0} },
105 { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
106 { ClkWinTitle, 0, Button2, zoom, {0} },
107 { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
108 { ClkClientWin, MODKEY, Button1, movemouse, {0} },
109 { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
110 { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
111 { ClkTagBar, 0, Button1, view, {0} },
112 { ClkTagBar, 0, Button3, toggleview, {0} },
113 { ClkTagBar, MODKEY, Button1, tag, {0} },
114 { ClkTagBar, MODKEY, Button3, toggletag, {0} },
115};
The structure parallels the keyboard configuration. Though with a slightly altered arrangement.
The first item refers to the category of click event that occurs, specifically where on the default status bar or client window the user clicks.
Then there is a bitwise event mask that is either 0 for no keys held or some combination of modifier keys.
The third item indicates the button the user clicks.
Then, the C function dwm calls when the modifier, mouse click, and click event occur.
Lastly, the arguments dwm should pass into the function.
This functionality is mostly for the convenience of the user who is already working with the mouse, such as in a web browser. In general, users of tiling window managers tend to operate from the philosophy that the need for reaching from the keyboard to the mouse is a design flaw. Why remove your hands from the keyboard where you can perform so many operations so much faster to a mouse where you have to search for a thing and then can only do one thing at a time?