Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

keyd only remaps laptop keyboard #226346

Closed
kylechui opened this issue Apr 15, 2023 · 19 comments
Closed

keyd only remaps laptop keyboard #226346

kylechui opened this issue Apr 15, 2023 · 19 comments

Comments

@kylechui
Copy link
Contributor

Describe the bug

I'm using the experimental services.keyd to try and remap some keys. It remaps the keys properly on my laptop's built-in keyboard, but not an external keyboard that I plugged in.

Steps To Reproduce

Steps to reproduce the behavior:

  1. Use the unstable version of nixpkgs
  2. Set this in configuration.nix
{
  # ...
  services.keyd = {
    enable = true;
    ids = [ "*" ];
    settings = {
      main = {
        capslock = "overload(meta, esc)";
        esc = "capslock";
      };
    };
  };
}

Expected behavior

Since ids is set to [ "*" ], all keyboards should have their bindings remapped, regardless of whether they are internal or not.

Screenshots

N/A

Additional context

I am running NixOS 22.11 and am relatively new to Nix, so please let me know if there's anything I'm doing incorrectly.

Notify maintainers

Metadata

Please run nix-shell -p nix-info --run "nix-info -m" and paste the result.

[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.1.23, NixOS, 23.05 (Stoat), 23.05.20230411.3fb8eed`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.13.3`
 - channels(root): `"home-manager-22.11.tar.gz, nixos-22.11"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
@woojiq
Copy link
Contributor

woojiq commented Apr 16, 2023

Hi @kylechui, I'm the developer of this service. Tbh, it's really experimental :) When I was writing and testing it also worked with external keyboards if I remember correctly. But now I plugged in a USB keyboard and it doesn't work. I will try to investigate this issue and report back. I also noticed some strange behavior that I haven't resolved yet but want to note: sometimes if you do nixos-rebuild, your keyboard stops working completely except some fn keys, I was able to resolve this by restarting my laptop. Really strange problem. I'm glad keyd isn't that popular so my crooked hands won't affect many people 😢

@woojiq
Copy link
Contributor

woojiq commented Apr 16, 2023

Mini update. I found that everything works fine if I plug in the keyboard before turning on the laptop. But if you connect after that, it will not work.
As a temporary workaround, you can restart the keyd service (sudo systemctl restart keyd or backspace+escape+enter) after connecting, this will also work.
And if you also have a problem where the keyboard stops working completely, try backspace+escape+enter:

Note: It is possible to render your machine unusable with a bad config file. Should you find yourself in this position, the special key sequence backspace+escape+enter should cause keyd to terminate.

Although it says that keyd will terminate, but in my case it just starts working properly.

@woojiq
Copy link
Contributor

woojiq commented Apr 16, 2023

I remembered. At first it worked because I did not use the DynamicUser option in the systemd service configuration. But then PR reviewer asked for a better sandbox, I added DynamicUser and with this configuration I didn't manually test with a second keyboard. And now I can confirm that the problem is with DynamicUser, it is not responding to new connected devices in runtime though restarting the service helps. If I register the service as root (uid 0) everything works fine.

@pennae you don't know what it could be related to?

@pennae
Copy link
Contributor

pennae commented Apr 16, 2023

@ybnesm could be that this is another problem with DeviceAllow. if removing that doesn't fix the problem we'll probably have to drop DynamicUser and run as a fixed user with sufficient group permissions (or root, if all else fails)

@woojiq
Copy link
Contributor

woojiq commented Apr 16, 2023

@ybnesm could be that this is another problem with DeviceAllow. if removing that doesn't fix the problem we'll probably have to drop DynamicUser and run as a fixed user with sufficient group permissions (or root, if all else fails)

No, it doesn't work without DeviceAllow either. Can we just run as root without too much effort like here. This will not damage the system and will be a little easier to maintain.

@pennae
Copy link
Contributor

pennae commented Apr 16, 2023

running as root is very not great, but if it's the only way to get this working then send it. don't have the time to try and debug this, until someone does a broken service doesn't help anyone

@kylechui
Copy link
Contributor Author

I remembered. At first it worked because I did not use the DynamicUser option in the systemd service configuration. But then PR reviewer asked for a better sandbox, I added DynamicUser and with this configuration I didn't manually test with a second keyboard. And now I can confirm that the problem is with DynamicUser, it is not responding to new connected devices in runtime though restarting the service helps. If I register the service as root (uid 0) everything works fine.

@pennae you don't know what it could be related to?

@ybnesm No worries about the stability, I'm just glad that you took the time to even create this service at all :) Based on what you've shared here, I assume something like sudo systemctl restart keyd.service would serve as a temporary workaround then (i.e. in an i3 or zsh startup configuration)?

@woojiq
Copy link
Contributor

woojiq commented Apr 16, 2023

@ybnesm No worries about the stability, I'm just glad that you took the time to even create this service at all :) Based on what you've shared here, I assume something like sudo systemctl restart keyd.service would serve as a temporary workaround then (i.e. in an i3 or zsh startup configuration)?

No, if you plug in the keyboard before turning on the laptop, it should work fine (in my case it works). But if you turn on the laptop and then plug in the keyboard you may restart the service as a workaround.

@kylechui
Copy link
Contributor Author

kylechui commented Apr 16, 2023

Tangentially related, but keyd also has an issue with laptop keyboards where libinput's DisableWhileTyping feature doesn't work on laptops while keyd is running. It has something to do with the fact that keyd generates a virtual keyboard/pointer (which makes it harder to match touchpad/keyboard), and is solved using device quirks, but I'm not experienced enough to figure out how to "make it work". If possible, some way to build this into the service would be much appreciated and would help alleviate this "gotcha" :)

Edit: I tried restarting the service and it works great now!

@woojiq
Copy link
Contributor

woojiq commented Apr 17, 2023

If possible, some way to build this into the service would be much appreciated and would help alleviate this "gotcha" :)

I'll try to add it as an extra option "libinputQuirks = true" or something like that. Sometimes I also suffer without DisableWhileTyping.

@waot
Copy link

waot commented May 5, 2023

@woojiq Not sure if this is the right place to ask, but as the author of the service module, would you be able to confirm whether the application specific config works for keyd on NixOS?

@woojiq
Copy link
Contributor

woojiq commented May 6, 2023

@woojiq Not sure if this is the right place to ask, but as the author of the service module, would you be able to confirm whether the application specific config works for keyd on NixOS?

I've never used this configuration in keyd so Idk. As far as I know this should work, but if not, it's the same problem with DynamicUser. Can you try and If it doesn't work, let me know, I'll try to fix it asap)

@waot
Copy link

waot commented May 16, 2023

Can you try and If it doesn't work, let me know, I'll try to fix it asap)

@woojiq For me it didn't work, but then again, I am relatively new to NixOS, so I am not sure whether it was due to my unstable keyd package, as I am stable Nix with everything else. So to the best of my abilities, I think the application-specific config didn't work. However, I ended solving my problem by rebinding the keys within the application, which was possible in this case.

But I'd say, definitely look into this before the package/service gets moved to stable. Will look forward to using the service in the future though, for other applications, as it is just a handy tool to have in ones toolbelt.

@woojiq
Copy link
Contributor

woojiq commented May 16, 2023

@waot Check it out https://github.com/rvaiya/keyd#application-specific-remapping-experimental. As you can see, you need to write these settings in the .config folder, not /etc/keyd/default.conf as my service does, so these are user settings and not global on the computer. I only realized it now. Currently, my keyd service does not support this configuration. I know it is possible to declaratively create files in the user's home directory with home-manager, but not sure about nixos directly. Maybe it could be another service inside home-manager or I need to find a way to write files to the config folder without home-manager.

As a "temporary" workaround, if you use home-manager, you can set the configuration file ~/.config/keyd/app.conf to be writable using the xdg.configFile command (https://mipmip.github.io/home-manager-option-search/) and run keyd-application-mapper at startup (read keyd manual section about exact steps). If you don't use home-manager, you can create a configuration file manually as you would on any other OS.

P.S. If you have any more questions, it's best to create a new issue as I expect this issue to be closed tomorrow 😃

@woojiq
Copy link
Contributor

woojiq commented May 16, 2023

@kylechui, the bug is fixed. Update unstable packages to the latest ones. Can you confirm that everything is working properly? And if it works, you can close this issue.

I tried adding features to enable the "Disable while typing" feature but it didn't work 😞 I've looked through the keyd issue/discussion and commit history a few times, it looks like it won't be easy to do. The author himself recently removed the quirks from repo, because many cornerstones derive from this.

@kylechui
Copy link
Contributor Author

I'm still a bit new to Nix, and couldn't find out how to update the packages repository. Since I'm using Home-manager with a flake, I thought that rebuilding might do the trick but it doesn't seem to be the case, nor did nix-channel --update. How would I update nixpkgs itself?

@woojiq
Copy link
Contributor

woojiq commented May 17, 2023

I'm still a bit new to Nix, and couldn't find out how to update the packages repository. Since I'm using Home-manager with a flake, I thought that rebuilding might do the trick but it doesn't seem to be the case, nor did nix-channel --update. How would I update nixpkgs itself?

Before rebuilding you need to update your flake.lock file.
If you are using flakes, these 2 commands will do the trick:
sudo nix flake lock --update-input nixpkgs1 - This command updates your flake.lock file so the next update will use the new packages. You can also use sudo nix flake update to update all inputs from flake.nix not only nixpkgs but also external flakes. In this case, both are correct.
sudo nixos-rebuild switch --flake .#flakename - this command rebuilds the system with respect to the flake.lock file. You can test instead of switch to temporarily test the changes and if everything works correctly - switch.

Footnotes

  1. https://discourse.nixos.org/t/how-to-update-a-single-flake-input/13584/6

@kylechui
Copy link
Contributor Author

Thanks for the help; things are looking good from my end!

@zeorin
Copy link
Contributor

zeorin commented Jan 15, 2024

I dug into this a little bit, and it seems the permissions that are given to the process by systemd only affect devices that were already there by the time the service starts, hence, plugging in a keyboard after it's started will not work.

I tried to fix this using the following udev rule:

SUBSYSTEM=="input", ACTION=="add", ATTR{name}!="keyd virtual*", RUN+="${pkgs.systemd}/bin/systemctl try-restart keyd.service"

This restarts the service when a keyboard is added (if the service was already started… else try-restart should no-op), but I can no longer get the actual service working with DynamicUser=true! I don't know why, but no matter what I try, keyd reports open uinput: Permission denied.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants