Skip to content

Key Bindings

Bakkeby edited this page Feb 27, 2024 · 4 revisions

Key bindings allow for key combinations to trigger designated function calls.

These are defined in the keys array in config.h. Refer to that for practical examples.

Each button binding have five values as defined by the Button struct:

typedef struct {
	int type;
	unsigned int mod;
	KeySym keysym;
	void (*func)(const Arg *);
	const Arg arg;
} Key;

The first three are filters and the function and argument is what will be evaluated if the conditions matches the filters.

type

The type value indicates whether the keybinding is to trigger on a key press or key release.

This has only two allowed values which are KeyPress and KeyRelease. The situations where a key release binding is favourable over triggering on a key press are very limited.

If in doubt use KeyPress here.

modifier

The modifier is used to differentiate between a plain key presses and when a modifier key is held down when the key is clicked. An example modifier key would be Super or Alt.

You can also combine modifiers for the key binding, e.g. Super|Ctrl will require the user to hold both modifiers down in addition to the key to trigger the function.

In practice all keybindings should be associated with a modifier as otherwise the keys will not be available for general typing.

Window managers typically have a primary modifier key for window management and this is more often than not the Super key (a.k.a. the Windows key). The primary modifier is set via the MODKEY macro in the configuration file.

Using modifiers such as Alt or Ctrl as the primary modifier can be disadvantageous as many applications use these modifiers for program specific keyboard shortcuts, in which case the window manager bindings would take precedence.

key

This represents the actual key that is pressed alongside the modifier to trigger the function call.

Symbolic keys do not follow any particular naming pattern, for example the tab character is XK_Tab whereas the + character is XK_plus. The symbolic keys are case sensitive.

Symbolic key names are usually found by running the xev utility (a.k.a. the Event Tester) which opens a white window where you can press keys and it will give you information on what key was pressed.

Here is an example when pressing the # character inside that window:

KeyPress event, serial 35, synthetic NO, window 0x6200001,
    root 0x6bf, subw 0x0, time 29757209, (511,150), root:(521,1135),
    state 0x0, keycode 51 (keysym 0x23, numbersign), same_screen YES,
    XLookupString gives 1 bytes: (23) "#"
    XmbLookupString gives 1 bytes: (23) "#"
    XFilterEvent returns: False

The symbolic name is reported as "numbersign", which means that we can add a keybinding by using the XK_numbersign. The XK_ prefix comes from the underlying libraries used.

function

This is the function that will be called if the key press conditions matches all the filters for the key binding.

The signature of the function is that it needs to take a constant Arg argument and not return anything:

void (*func)(const Arg *arg);

Refer to the Functions page for options. Not all functions have predefined key bindings in the default configuration.

argument

The argument set here will be passed to the function when it is evaluated.

Functions often rely on the state of the window manager for performing actions. A typical example would be a function using the currently selected client for its operation.


You may also want to refer to external tools such as sxhkd to handle some form of key bindings.

As an example this can allow for key chains and key modes which can allow for clustering of key bindings that is rarely used.


Back to Configuration.

Clone this wiki locally