jtroo / kanata

Improve keyboard comfort and usability with advanced customization
GNU Lesser General Public License v3.0
2.16k stars 112 forks source link

Feature request: multi-layer input chords #737

Closed prescientmoon closed 5 months ago

prescientmoon commented 7 months ago

Is your feature request related to a problem? Please describe.

I have a ton of input chords, but I'm not sure there's a way to keep them in the same places across many layers (qwert, colemak, symbol layers, etc).

Describe the solution you'd like.

I'm not sure what the best solution would be. A somewhat elegant solution would be having some way to declare a "pinend" layer which always stays at the top of the layer stack, and gets processed before everything else. Then chords could be placed on said layer, and individual keys could resolve to transparent keys, letting the underlying stack handle the event.

Describe alternatives you've considered.

Additional context

I think qmk combos are pretty global, unless I am misremembering.

jtroo commented 7 months ago

generate chord sets for every layer

require duplicating about 100 lines

It's not clear to me why this is necessary - it seems like you could reuse the same chord set. Could you provide some sample configuration to aid my understanding?

rszyma commented 7 months ago

Then chords could be placed on said layer, and individual keys could resolve to transparent keys, letting the underlying stack handle the event.

fyi, currently, in multiple "stacked" layers with layer-while-held transparent keys do not resolve one layer below, but to the "bottom" layer. This was also mentioned while discussing #635.

prescientmoon commented 7 months ago

generate chord sets for every layer

require duplicating about 100 lines

It's not clear to me why this is necessary - it seems like you could reuse the same chord set. Could you provide some sample configuration to aid my understanding?

My chords are conceptually chosen based on their physical position on the keyboard, not based on the underlying keys. For instance, on my qwerty layer I want sd to resolve to shift, but I want the individual keys to resolve to s and d respectively. Were I to reuse said chords on a colemak layer, pressing s by itself would type r, and pressing d by itself would type s, even if pressing rs (i.e. the colenak keys in the physical location of sd in qwerty) would resolve to shift (the correct output).

prescientmoon commented 7 months ago

I will say, that currently working with big chord sets (10+ keys involved) requires a lot of boilerplate lines of just "if only <x> is pressed, return <x>" and "alias @ch<x> to chord ... <x>" (for every possible involved key x). It would be very nice if the system was a bit easier to use, especially because the things outlined above are probably the most common usecase. I might also be missing an easier existing way to config this.

prescientmoon commented 7 months ago

I'll provide my actual config in a bit when I'm in front of my pc.

rszyma commented 7 months ago

If both #738 and #635 were to be resolved I'm pretty sure could use _ in chord definition to have generic chords to avoid this kind of repetition.

prescientmoon commented 7 months ago

If both #738 and #635 were to be resolved I'm pretty sure could use _ in chord definition to have generic chords to avoid this kind of repetition.

Yeah, but I would still need a way to always pin the chord layer to the top of the stack, right?

rszyma commented 7 months ago

In theory the following would work: place all chords in a separate layer (let's call it "chords") and replace all

(layer while-held <layer_name>)

with

(multi (layer-while-held <layer_name>) (layer-while-held chords))
prescientmoon commented 7 months ago

In theory the following would work: place all chords in a separate layer (let's call it "chords") and replace all

(layer while-held <layer_name>)

with

(multi (layer-while-held <layer_name>) (layer-while-held chords))

What about the base layer? Would each key have to be changed to activate the additional layer?

I think with enough changes this could be acomplished, but it still feels like the system makes common uses of chords difficult, and certain rarer uses easy.

I think conceptually the stacking happens "vertically", while we want chords to compose "horizontally". That is, if layers allow defining conceptual "functions from streams of key events to streams of key events", then we essentially want to be able to pass the output stream from the chord layer to the input stream of the normal layer. I actually think this wouldn't be unreasonable by just running two kanata instances in sequences (although assuming kanata uses uinput to simulate events, I'd have to figure out how to use that virtual device as the input for the next instance).

jantache-microsoft commented 7 months ago

I actually think this wouldn't be unreasonable by just running two kanata instances in sequences (although assuming kanata uses uinput to simulate events, I'd have to figure out how to use that virtual device as the input for the next instance).

This is certainly possible, and others have done so. There is even a --symlink_path configuration option to help with this use case.

jtroo commented 7 months ago

Some random disorganized thoughts:

Perhaps running two kanata instances is the best solution for this though, it does seem quite clean and seems to match the use case well. Unfortunately it's only confirmed to well on Linux. I'm not sure if Windows/macOS can reliably have a 2nd kanata instance intercepting the output of the 1st instance.

prescientmoon commented 7 months ago

I'm now realising that my double kanata instance idea, while still possible, is not quite as elegant as I thought.

In particular, I have some homerow chords for my alt keys, and I have my alt keys mapped to something else. So in order to be able to map the alt keys in the second instance, I'd have to map them to an unused intermediate key in the first instance, if that makes any sense.

jtroo commented 7 months ago

@Mateiadrielrafael Instead of trying to directly solve the transparency issue or change how chord behaviour works, since those are more difficult problems with nebulous fixes, I instead got the motivation to add template functionality to help with repetitive configurations.

Please see how it looks when you get a chance

prescientmoon commented 7 months ago

@Mateiadrielrafael Instead of trying to directly solve the transparency issue or change how chord behaviour works, since those are more difficult problems with nebulous fixes, I instead got the motivation to add template functionality to help with repetitive configurations.

Please see how it looks when you get a chance

* [PR](https://github.com/jtroo/kanata/pull/745)

* [docs](https://github.com/jtroo/kanata/blob/main/docs/config.adoc?rgh-link-date=2024-02-16T08%3A23%3A38Z#templates)

That's a nice feature to have, although for me in particular I think nix would offer more power in this situation. I might end up ditching the idea of trying to have both a qwerty and a colemak layer and call it a day though.

jtroo commented 5 months ago

Adjacently fixed by https://github.com/jtroo/kanata/pull/916