You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Kaleidoscope/docs/layers.md

147 lines
7.5 KiB

# Layers
Layers are an integral part of Kaleidoscope, but a part that is perhaps harder
to master than many other things in the firmware. On these pages, we'll make an
attempt at explaining layers, what you can do with them, how, and a few common
use-cases.
We'll start with a quick use-case guide, before diving deeper into explanations!
## How do I...?
### How do I switch to a layer, so I can type multiple keys from there?
You can use `LockLayer(n)` or `MoveToLayer(n)`, depending on whether you want
other layers to be active at the same time or not. `LockLayer(n)` allows you to
build up a stack of layers, while with `MoveToLayer(n)` only the selected layer
will be active, without any stacking.
### How do I do make layer switching act similar to modifiers?
If you want the layer switch to be active only while the key is held, like in
the case of modifiers, the `ShiftToLayer(n)` method does just that.
While switching layers this way is similar to how modifiers work, there are
subtle differences. For a longer explanation, see
[later](#layers-transparency-and-how-lookup-works).
## Layer theory
First of all, the most important thing to remember is that layers are like a
piece of foil, you can place many of them on top of each other, and see through
uncovered parts. In other words, you can have multiple layers all active at the
same time! As we'll see a few paragraphs later, this can be a very powerful
thing.
To better explain how this works in practice, lets look at what layer-related
keys we can place on the keymap first. Armed with that knowledge, we'll then
explore a few use-cases.
## Layer keys
- `LockLayer(n)`: Locking a layer will activate it when the key toggles on, and
the layer will remain active until unlocked (with `UnlockLayer(n)` or by
pressing `LockLayer(n)` again), even if we release the layer key
meanwhile. Think of it like a `Caps lock` or `Num lock` key.
- `ShiftToLayer(n)`: Unlike `LockLayer`, this only activates the layer until the
key is held. Once the key is released, the layer deactivates. This behaviour
is very similar to that of modifiers.
- `MoveToLayer(n)`: Moving to a layer is very similar to locking it, the only
exception is that moving disables all other layers, so only the moved to layer
will be active. This allows us to have a less powerful, but simpler way of
dealing with layers, as we'll see below.
- `Key_KeymapNext_Momentary` / `Key_KeymapPrevious_Momentary`: These activate
the next or the previous layer, momentarily, like `ShiftToLayer(n)`. What it
considers `next`, is one layer higher than the currently highest active layer.
Similarly, `previous` is one below the currently highest active layer.
## Use cases
### Locked layers
Locked layers are most useful when you'll want to spend more time on the target
layer. One such case is the numpad: when using it, we usually want to enter
longer numbers, or use the mathematical operator keys as well. Just imagine
hitting a layer lock key, and the right half of your keyboard turning into a
numpad! It's closer than the numpad on traditional full-size keyboards, thus
less hand movement is required!
### Shifted layers
There are many great examples for shifted layers, such as a symbols layer. Let's
say we have a number of often used symbols which we want easy access to,
preferably near the home row. For example, the various parentheses, brackets and
the like are often used in programming. Having them on the home row is
incredibly convenient. In most cases, we only need this layer for a very short
time, for a symbol or two. As such, locking the layer would be
counter-productive. Instead, we use a layer shift key, like if it was a
modifier.
As a concrete example, let's imagine a small, ortholinear keyboard, like the
Planck. On the bottom row, on the right side of the space bar, we'd have a layer
shift key (lets call that `Fn` for now), that takes us to the symbol layer. On
the symbol layer, we'd have `{`, `}`, `[`, `]`, `(`, and `)` on the home row. To
input `{`, we'd press `Fn + d`, for example. This is still two presses, very
much like `Shift + [`, but the keys are more convenient, because we use stronger
fingers to press them.
Another - and perhaps an even better - example would be a navigation layer, with
cursor keys laid over `WASD`. The reason why this would be a better example, is
because in this case, we often want to use modifiers along with the cursor keys,
such as `Shift` or `Control`. With a shifted layer, if we have transparent keys
at positions where the modifiers are on the base layer, we don't have to repeat
the modifier layout on the shifted layer! This makes it easier to experiment
with one's layout, because if we move modifiers, we only have to do that on one
layer.
### Moving to layers
Moving to a layer is very similar to locking one. The only difference is that
moving disables all other layers. This in turn, has consequences: we can't
return to the previous layer state by repeating the same key. Unlocking a layer
that has been activated by `MoveToLayer(n)` will instead cause Kaleidoscope to
fall back to the default base layer.
The major advantage of moving to a layer - as opposed to locking one - is the
cognitive load. With moving, there is no transparency.[^1] There is only one layer
active at any given time. It's a simpler concept to grasp.
## Layers, transparency, and how lookup works
The thing that confuses many people about layers is that they can have
transparency. What even is a transparent key? Remember the first paragraphs:
layers are like a foil. They're see-through, unless parts of it are obstructed.
They're like overrides. Any layer you place on top of the existing stack, will
override keys in the layers below.
When you have multiple layers active, to figure out what a key does, the
firmware will first look at the key position on the most recently activated
layer, and see if there's a non-transparent key there. If there is, it will use
that. If there isn't, it will start walking backwards on the stack of _active_
layers to find the highest one with a non-transparent key. The first one it
finds is whose key it will use. If it finds none, then a transparent key will
act like a blank one, and do nothing.[^1]
It is important to note that transparent keys are looked up from active layers
only, from most recently activated to least. Lets consider that we have three
layers, 0, 1, and 2. On a given position, we have a non-transparent key on
layers 0 and 1, but the same position is transparent on layer 2. If we have
layer 0 and 2 active, the key will be looked up from layer 0, because layer 2 is
transparent. If we activate layer 1 too, it will be looked up from there, since
layer 1 is higher in the stack than layer 0. In this case, since we activated
layer 1 most recently, layer 2 wouldn't even be looked at.
As we just saw, another important factor is that layers are ordered by their
order of activation. Whether you activate layer 1 or 2 first, matters. Lets look
at another example: we have three layers, 0, 1, and 2. On a given position, we
have a non-transparent key on every layer. If we have just layer 0 active, it
will be looked up from there. If we activate layer 2, then the firmware will
look there first. If we activate layer 1 as well, then - since now layer 1 is
the most recently activated layer - the firmware will look the code up from
layer 1, without looking at layer 2. It would only look at layer 2 if the key
was transparent on layer 1.
[^1]: Except that the base layer is always active implicitly, so if all active
layers are transparent for a particular key, its value will come from the
base layer.