rvaiya / keyd

A key remapping daemon for linux.
MIT License
2.72k stars 157 forks source link

[ids] for keyd-application-mapper? #264

Closed suderman closed 2 years ago

suderman commented 2 years ago

Firstly, I really enjoy this software and I'm so happy it exist. Thank you!! ^_^

I have a situation where I need application-specific masks in app.conf to vary depending on which keyboard I'm using. Or maybe I just need another approach I haven't considered.

Here's my usecase:

My laptop's internal keyboard's modifier keys are originally laid out as [control][meta][alt][space] but keyd rearranges them to [meta][alt][ctrl][space] This resembles a Mac-like layout, similar to what kinto.sh does. However, when terminal apps have focus, I like to temporarily change this to [meta][alt][meta][space] and keyd-application-mapper does the job.

Here's an excerpt of my default.conf and app.conf:

[control_cmd:C]

x = S-delete
c = C-insert
v = S-insert

[meta_cmd:M]

x = S-delete
c = C-insert
v = S-insert

[main]

capslock = overload(control, esc)
leftcontrol = layer(meta)
leftmeta = layer(alt)
leftalt = overload(control_cmd, macro(leftmeta))
rightalt = layer(meta)
[org-wezfurlong-wezterm]

leftalt = layer(meta_cmd)

This works great, and gives me consistent keyboard motions to create new tabs (command-T) in both Firefox and WezTerm.

However, I also have an external keyboard with a Mac layout, and the modifier keys are laid out differently: [ctrl][alt][meta][space] I can create a new keyd conf file using the [ids] header to target this keyboard, and adjust the [main] section like so:

[main]

capslock = overload(control, esc)
leftcontrol = layer(meta)
leftmeta = overload(control_cmd, macro(leftmeta))

The alt keys get left alone, because they're already where I want them. The leftmeta key now gets the overload action instead. This is fine until keyd-application-mapper gets involved, where app.conf still masks leftalt:

[org-wezfurlong-wezterm]

leftalt = layer(meta_cmd)

For this external keyboard, I need to override leftmeta instead of leftalt. But I can't update this without breaking the configuration for my laptop's internal keyboard.

How do I make both keyboards work?

rvaiya commented 2 years ago

Unfortunately application specific bindings can't apply to a specific id. I will probably add some syntax for this in an upcoming release. One thing you might try in the meantime is simply redefining keys within control_cmd to behave as their corresponding alt sequences.

E.G

[org-wezfurlong-wezterm]

control_cmd.a = A-a
control_cmd.b = A-b
....

Which should work since you have defined both leftalt and leftmeta to control_cmd on their respective keyboards.

This has the disadvantage of requiring you to explicitly define each key, and won't capture some of the subtle behaviours of a properly modified layer (e.g immediate actuation, modified clicks, etc), but might be good enough for your intended use case.

P.S

Instead of overload(control_cmd, macro(leftmeta)) you can just do overload(control_cmd, leftmeta).

suderman commented 2 years ago

Thank you for your feedback, I'll consider how that may work for me.

As for the overload action, you're right that it works without the macro, but I had to wrap leftmeta in a macro to suppress this warning:

WARNING: mapping modifier keycodes directly may produce unintended results, you probably want layer(<modifier name>) instead
suderman commented 2 years ago

I have another approach to consider, but it would require a new feature: key aliases defined in /etc/keyd/*.conf. This would allow a unified configuration for varying keyboard layouts--typically Mac and PC keyboards with the Alt and Meta keys swapped.

Something like this:

/etc/keyd/framework.conf

[ids]

# Framework Laptop
0001:0001

# Define alias key names for keyboards with the above id(s)
leftoption = alias_of(leftmeta)
leftcommand = alias_of(leftalt)

[main]

# Assign actions to aliases instead of direct key names
leftoption = layer(alt)
leftcommand = overload(control_cmd, macro(leftcommand))

/etc/keyd/hhkb.conf

[ids]

# HHKB external keyboard
0853:0100

# These keys have switched places on this keyboard
leftoption = alias_of(leftalt)
leftcommand = alias_of(leftmeta)

[main]

# Using aliases, this excerpt of [main] doesn't need to be different
leftoption = layer(alt)
leftcommand = overload(control_cmd, macro(leftcommand))

~/.config/keyd/app.conf

[org-wezfurlong-wezterm]

# Using my configuration's leftcommand alias, this rule now works for both keyboards
leftcommand = layer(meta_cmd)

Just an idea. :-)

rvaiya commented 2 years ago

I have another approach to consider, but it would require a new feature: key aliases defined in /etc/keyd/*.conf.

I originally considered doing something similar with keycodes. The idea was to have some notion of a 'base layer' in which lefthand values (keycodes) could be reassigned before parsing the rest of the config file in order to facilitate identical configs with slightly different hardware (like a QMK keymap). The user could theoretically then recycle the same config file by making minimal changes in the base layer. Your alias proposal is essentially the same thing with the addition that names don't have to be valid keycodes.

I didn't end up implementing it because I wanted to reduce unnecessary complexity, and include didn't exist at the time, but I think it solves the current problem more elegantly and intend to include something similar in the next release.

rvaiya commented 2 years ago

I've added support for aliases in the latest commit.

suderman commented 2 years ago

Amazing! And I haven't tried includes before now, but that's a perfect match with this new feature. It's working great. Thank you!

rvaiya commented 2 years ago

Just a heads up, I ended up inverting the syntax because I found <key> = <name> more intuitive (especially in the case of key->key aliasing). This is fair game since the syntax is relatively new and hasn't been ratified in the form of a new release. Let me know if you have any objections.