speedwm-personal/docs/doc-11.md

7.8 KiB

12. Keybinds

Like the bar array mentioned previously, there is a Key keys array in keybinds.h which contains all keybinds speedwm will recognize. While this isn't the only way to add keybinds in speedwm, it does not require any additional software to be installed.

Key structure

  1. Event

Internally: int type

  1. Modifier

Internally: unsigned int mod

  1. Chain key

Internally: KeySym chain

  1. Key

Internally: KeySym keysym

  1. Function

Internally: void (*func)(const Arg *)

  1. Function arguments

Internally: const Arg arg

Event

The event value allow you to specify when a keybind is executed. Internally this is known as int type and it specifies when the function is executed.

  • KeyPress: Activate immediately on key press.
  • KeyRelease: Activate immediately on key release.

Modifier

There are a lot of different modifiers, this list is only going to list the ones declared in speedwm. You can, of course declare more if necessary although it should be noted that doing so is out of the scope of this documentation. We will be focusing on the defined modifiers which are defined in speedwm.c like this:

/* Modifiers */ #define CONTROL ControlMask #define SHIFT ShiftMask #define ALT Mod1Mask #define ALTR Mod3Mask #define SUPER Mod4Mask #define SUPERR Mod5Mask

Below is a list of defined modifiers:

  • CONTROL Left Control (Ctrl) key.
  • SHIFT Left Shift key.
  • ALT Left Alt key.
  • SUPER Left Super (Windows) key.
  • SUPERR Right Super (Windows) key.

In keybinds.h, MODIFIER1 and MODIFIER2 are also defined. MODIFIER1 is defined in order to make modifying keybinds easier. MODIFIER1 is by default defined as SUPER or Mod4Mask. For instance, if you want to use MODIFIER1 as your modifier, MODIFIER1 would be the right value here.

Do note that you can may use multiple modifiers. Do this by adding two or more modifiers separated by a pipe (MODIFIER1|SHIFT)

Chain key

This value is mandatory, but it does not have to be used. speedwm has supported chained keybinds since 0.4. Chained keybinds allow more keybinds as like the name implies, the user has to press multiple keys to activate it. You can think of it as in Vim where there's different modes.

The first key that needs to be pressed to activate a chain needs to be the key specified here. In order to see a list of possible keys, see /usr/include/X11/keysymdef.h. If, let's say we want to use simply the letter a as the key to start a chain, the value here would be XK_a.

If we want a normal key, one that is not chained, we can accomplish that by simply setting the Chain key to -1. You can see this in the keypress() function in speedwm.c. This line of code is responsible for this behavior.

if (keysym == keys[i].keysym && keys[i].chain == -1

Key

The next value, similar to the Chain key also needs to be a keysym. If the key is a chained key, this is the second key that needs to be pressed. If it isn't a chained key, this is the key that needs to be pressed while the Modifier is pressed.

In order to see a list of possible keys, see /usr/include/X11/keysymdef.h. Note that this path may differ depending on your operating system.

There are a lot more keys technically defined, see /usr/include/X11/XF86keysym.h for a list of media keys.

Function

Many functions expect const Arg *arg to be passed to them. However this value does require any function argument to be specified because it simply passes the next value to the function and calls it.

There is no list of functions, but speedwm.c has a lot of declared functions which you may use in keybinds provided the function expects const Arg *arg.

Function arguments

This is the actual argument passed to the function we're calling when the keybind is activated. Explaining this well would be fairly simple, but instead of doing so I recommend you read the typedef union Arg in speedwm.c. It looks like this:

typedef union { long i; unsigned long ui; float f; const void *v; } Arg;

In short, Arg is a list of different types, which may be used to set different things in the argument. Passing a float (such as mfact) through would mean I should override .f, passing an integer (such as barposition) through would mean I should override .i. There's also .v for void and .ui for tags. This is not used unless you want to mess with tag keybinds.

When you don't care about the value given to the function, you may simply enter a 0.

Example keybind

With all that said, you probably get the idea of how it works. But you still don't know how to put all this knowledge together.

  1. { KeyPress,
  2. MODIFIER1|SHIFT,
  3. -1,
  4. XK_w,
  5. spawn,
  6. cmd( "firefox" ) },

Combined into one line: { KeyPress, MODIFIER1|SHIFT, -1, XK_w, spawn, cmd( "firefox" ) },

Let's break down the above.

  1. This is our type. If it's KeyPress, it will be activated when the keybind is pressed. If it is KeyRelease it will be activated when the keybind is released.
  2. This is our modifier. MODIFIER1 is defined in keybinds.h. We're adding SHIFT to it, (defined in speedwm.c) which means we have to press BOTH MODIFIER1 and SHIFT at the same time to activate this keybind.
  3. This is our chain key. -1 here indicates that we do not want it to be chained. We want a regular keybind. See the example below for an example with a chained keybind instead.
  4. This is our regular key. XK_w is defined in /usr/include/X11/keysymdef.h on most operating systems and it means we have to press w on our keyboard along with the modifier to activate this keybind.
  5. This is our function. We call this, passing the next value (const Arg *arg) to it.
  6. This is our function argument. Do note that in this case cmd() is a macro and it is defined in speedwm.c. This macro will pass the contents of the macro to a shell it will spawn.

Feel free to copy the above to keybinds.h if you want to experiment with it.

Example chained keybind

  1. { KeyPress,
  2. MODIFIER1|SHIFT,
  3. XK_a,
  4. XK_w,
  5. togglebar,
  6. {0} },

Combined into one line: { KeyPress, MODIFIER1|SHIFT, XK_a, XK_w, togglebar, {0} },

Let's break down the above.

  1. This is our type. If it's KeyPress, it will be activated when the keybind is pressed. If it is KeyRelease it will be activated when the keybind is released.
  2. This is our modifier. MODIFIER1 is defined in keybinds.h. We're adding SHIFT to it, (defined in speedwm.c) which means we have to press BOTH MODIFIER1 and SHIFT at the same time to activate this keybind.
  3. This is our chain key. XK_a here is the key we have to press along with our modifier to activate this keybind. XK_a is defined in /usr/include/X11/keysymdef.h on most operating systems.
  4. This is our regular key. XK_w is defined in /usr/include/X11/keysymdef.h on most operating systems and it means we have to press w on our keyboard to activate this keybind. Note that we do not need to press the modifier here, because it is a chained keybind.
  5. This is our function. We call this, passing the next value (const Arg *arg) to it.
  6. This is our function argument. We simply pass 0 here because we don't need to pass anything to the function, because the function does not care.

Feel free to copy the above to keybinds.h if you want to experiment with it.

This should give you a brief idea of how keybinds work in speedwm. Most of this carries over to dwm as well, although it does not have some of this stuff. It should be noted that as I mentioned previously, you don't HAVE to use this system. You can use external programs to handle keybinds, and libspeedwm to perform actions in speedwm. sxkbd is one popular program for this purpose and window managers like bspwm use it. However such a solution is out of the scope of this documentation!