GithubHelp home page GithubHelp logo

jtroo / kanata Goto Github PK

View Code? Open in Web Editor NEW
1.4K 10.0 99.0 3.85 MB

Improve keyboard comfort and usability with advanced customization

License: GNU Lesser General Public License v3.0

Rust 98.64% Just 0.27% AutoHotkey 1.09%
keyboard rust cross-platform linux windows interception-driver keyboard-layout mouse mouse-emulation macos

kanata's Introduction

Kanata

Image of a keycap with the letter K on it in pink tones

Improve your keyboard comfort

What does this do?

This is a cross-platform software keyboard remapper for Linux, macOS and Windows. A short summary of the features:

  • multiple layers of key functionality
  • advanced key behaviour customization (e.g. tap-hold, macros, unicode)
  • cross-platform human readable configuration file

Check out the examples directory and the online simulator.

To see all of the features, see the configuration guide. The configuration guide aims to be up-to-date with main and may have features not in your version. See the applicable link in the releases page.

The most similar project is kmonad, which served as the inspiration for kanata. Here's a comparison document.

You can see a list of known issues here.

Demo video

Showcase of multi-layer functionality (30s, 1.7 MB).

Why is this useful?

Imagine if, instead of pressing Shift to type uppercase letters, we had giant keyboards with separate keys for lowercase and uppercase letters. I hope we can all agree: that would be a terrible user experience!

A way to think of how Shift keys work is that they switch your input to another layer of functionality where you now type uppercase letters and symbols instead of lowercase letters and numbers.

What kanata allows you to do is take this alternate layer concept that Shift keys have and apply it to any key. You can then customize what those layers do to suit your exact needs and workflows.

Usage

Running kanata currently does not start it in a background process. You will need to keep the window that starts kanata running to keep kanata active. Some tips for running kanata in the background:

Pre-built executables

See the releases page for executables and instructions.

Build it yourself

This project uses the latest Rust stable toolchain. If you installed the Rust toolchain using rustup, e.g. by using the instructions from the official website, you can get the latest stable toolchain with rustup update stable.

Instructions

Using cargo install:

cargo install kanata

# On Linux and macOS, this may not work without `sudo`, see below
kanata --cfg <your_configuration_file>

Build and run yourself in Linux:

git clone https://github.com/jtroo/kanata && cd kanata
cargo build   # --release optional, not really perf sensitive

# sudo is used because kanata opens /dev/ files
#
# See below if you want to avoid needing sudo:
# https://github.com/jtroo/kanata/wiki/Avoid-using-sudo-on-Linux
sudo target/debug/kanata --cfg <your_configuration_file>

Build and run yourself in Windows.

git clone https://github.com/jtroo/kanata; cd kanata
cargo build   # --release optional, not really perf sensitive
target\debug\kanata --cfg <your_configuration_file>

Build and run yourself in macOS:

For macOS version 11 and newer: Install the Karabiner VirtualHiDDevice Driver.

To activate it:

/Applications/.Karabiner-VirtualHIDDevice-Manager.app/Contents/MacOS/Karabiner-VirtualHIDDevice-Manager activate

For macOS version 10 and older: Install the Karabiner kernel extension.

git clone https://github.com/jtroo/kanata && cd kanata
cargo build   # --release optional, not really perf sensitive

# sudo is needed to gain permission to intercept the keyboard

sudo target/debug/kanata --cfg <your_configuration_file>

The full configuration guide is found here.

Sample configuration files are found in cfg_samples. The simple.kbd file contains a basic configuration file that is hopefully easy to understand but does not contain all features. The kanata.kbd contains an example of all features with documentation. The release assets also have a kanata.kbd file that is tested to work with that release. All key names can be found in the keys module, and you can also define your own key names.

Feature flags

When either building yourself or using cargo install, you can add feature flags that enable functionality that is turned off by default.

Instructions

If you want to enable the cmd actions, add the flag --features cmd. For example:

cargo build --release --features cmd
cargo install --features cmd

On Windows, if you want to compile a binary that uses the Interception driver, you should add the flag --features interception_driver. For example:

cargo build --release --features interception_driver
cargo install --features interception_driver

To combine multiple flags, use a single --features flag and use a comma to separate the features. For example:

cargo build --release --features cmd,interception_driver
cargo install --features cmd,interception_driver

Other installation methods

Packaging status

Notable features

Contributing

Contributions are welcome!

Unless explicitly stated otherwise, your contributions to kanata will be made under the LGPL-3.0-only* license.

Some directories are exceptions:

Here's a basic low-effort design doc of kanata

How you can help

  • Try it out and let me know what you think. Feel free to file an issue or start a discussion.
  • Usability issues and unhelpful error messages are considered bugs that should be fixed. If you encounter any, I would be thankful if you file an issue.
  • Browse the open issues and help out if you are able and/or would like to. If you want to try contributing, feel free to ping jtroo for some pointers.
  • If you know anything about writing a keyboard driver for Windows, starting an open-source alternative to the Interception driver would be lovely.

Community projects related to kanata

What does the name mean?

I wanted a "k" word since this relates to keyboards. According to Wikipedia, kanata is an indigenous Iroquoian word meaning "village" or "settlement" and is the origin of Canada's name.

There's also PPT✧.

Motivation

TLDR: QMK features but for any keyboard, not just fancy mechanical ones.

Long version

I have a few keyboards that run QMK. QMK allows the user to customize the functionality of their keyboard to their heart's content.

One great use case of QMK is its ability map keys so that they overlap with the home row keys but are accessible on another layer. I won't comment on productivity, but I find this greatly helps with my keyboard comfort.

For example, these keys are on the right side of the keyboard:

7 8 9
u i o
j k l
m , .

On one layer I have arrow keys in the same position, and on another layer I have a numpad.

arrows:       numpad:
- - -         7 8 9
- ↑ -         4 5 6
← ↓ →         1 2 3
- - -         0 * .

One could add as many customizations as one likes to improve comfort, speed, etc. Personally my main motivator is comfort due to a repetitive strain injury in the past.

However, QMK doesn't run everywhere. In fact, it doesn't run on most hardware you can get. You can't get it to run on a laptop keyboard or any mainstream office keyboard. I believe that the comfort and empowerment QMK provides should be available to anyone with a computer on their existing hardware, instead of having to purchase an enthusiast mechanical keyboard (which are admittedly very nice — I own a few — but can be costly).

The best alternative solution that I found for keyboards that don't run QMK was kmonad. This is an excellent project and I recommend it if you want to try something similar.

The reason for this project's existence is that kmonad is written in Haskell and I have no idea how to begin contributing to a Haskell project. From an outsider's perspective I think Haskell is a great language but I really can't wrap my head around it. And there are a few outstanding issues at the time of writing that make kmonad suboptimal for my personal workflows.

This project is written in Rust because Rust is my favourite programming language and the prior work of the awesome keyberon crate exists.

Similar Projects

  • kmonad: The inspiration for kanata (Linux, Windows, Mac)
  • QMK: Open source keyboard firmware
  • keyberon: Rust #[no_std] library intended for keyboard firmware
  • ktrl: Linux-only keyboard customizer with layers, a TCP server, and audio support
  • kbremap: Windows-only keyboard customizer with layers and unicode
  • xcape: Linux-only tap-hold modifiers
  • karabiner-elements: Mac-only keyboard customizer
  • capsicain: Windows-only key remapper with driver-level key interception
  • keyd: Linux-only key remapper very similar to QMK, kmonad, and kanata
  • xremap: Linux-only application-aware key remapper inspired more by Emacs key sequences vs. QMK layers/Vim modes
  • keymapper: Context-aware cross-platform key remapper with a different transformation model (Linux, Windows, Mac)

Why the list?

While kanata is the best tool for some, it may not be the best tool for you. I'm happy to introduce you to tools that may better suit your needs. This list is also useful as reference/inspiration for functionality that could be added to kanata.

Donations/Support?

The author (jtroo) will not accept monetary donations for work on kanata. Please instead donate your time and/or money to charity.

Some links are below. These links are provided for learning and as interesting reads. They are not an endorsement.

kanata's People

Contributors

11kilobytes avatar andrewsmithdev avatar br-lemes avatar brockelmore avatar dependabot[bot] avatar eugenesvk avatar gerhard-h avatar itaygarin avatar jian-lin avatar johni0702 avatar jtroo avatar kageyam4 avatar kircheneer avatar lgug2z avatar moritzketzer avatar nightscape avatar oberblastmeister avatar octavec avatar pheon-dev avatar philipp-m avatar pinoinha avatar postsolar avatar psych3r avatar quazirate avatar reidprichard avatar rszyma avatar teras avatar thomasa88 avatar wis avatar wolfwood avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kanata's Issues

Bug: Transparent keys on base layer act as dead keys

Expected

Transparent keys (i.e. using underscore _) on the first layer should not be remapped at all, sending whatever key is defined in the defsrc declaration. This is how kmonad behaves.

Actual

Although input is registered and visible from debug logs, no key is output at all leaving these keys dead.

To Reproduce

Use the following config:

(defcfg)
(defsrc a f)
(deflayer one (layer-toggle two) _)
(deflayer two a z)

Tapping f sends no key. Holding a and then tapping f sends z as expected. Logs for this sequence:

$ ./target/debug/kanata.exe --cfg repro.kbd --debug
06:27:50 [INFO] Kanata: config parsed
06:27:50 [INFO] Kanata: entering the processing loop
06:27:50 [INFO] Init: catching only releases and sending immediately
06:27:51 [INFO] Starting kanata proper
06:27:59 [DEBUG] (2) kanata::kanata: event loop: KeyEvent { code: KEY_F, value: Press }
06:27:59 [DEBUG] (2) kanata::kanata: event loop: KeyEvent { code: KEY_F, value: Release }
06:28:01 [DEBUG] (2) kanata::kanata: event loop: KeyEvent { code: KEY_A, value: Press }
06:28:01 [INFO] Entered layer:
(deflayer two a z)
06:28:01 [DEBUG] (2) kanata::kanata: event loop: KeyEvent { code: KEY_F, value: Press }
06:28:01 [DEBUG] (3) kanata::kanata: press     Z
06:28:01 [DEBUG] (2) kanata::kanata: event loop: KeyEvent { code: KEY_F, value: Release }
06:28:01 [DEBUG] (3) kanata::kanata: release   Z
06:28:02 [DEBUG] (2) kanata::kanata: event loop: KeyEvent { code: KEY_A, value: Release }
06:28:02 [INFO] Entered layer:
(deflayer one (layer-toggle two) _)

System Info

I'm on Windows 10, compiling myself using the most recent main branch.

Doesn't work on Wayland

It seems kanata doesn't support Wayland. I've tested Plasma and Gnome on Wayland. Debug output shows kanata gets key presses, but doesn't return keycodes to the system.

08:19:23 [DEBUG] (2) kanata::kanata: press     A
08:19:23 [DEBUG] (2) kanata::oskbd::linux: input ev: InputEvent { time: TimeVal { tv_sec: 0, tv_usec: 0 }, event_type: EV_KEY, event_code: EV_KEY(KEY_A), value: 1 }
08:19:23 [DEBUG] (2) kanata::kanata: release   A
08:19:23 [DEBUG] (2) kanata::oskbd::linux: input ev: InputEvent { time: TimeVal { tv_sec: 0, tv_usec: 0 }, event_type: EV_KEY, event_code: EV_KEY(KEY_A), value: 0 }

Kanata under X11 works correctly. Probably it's not important, as I suspect there is no support at all, but I'm using

kwayland 5.94.0-2
kwayland-server 5.24.5-1
wayland 1.20.0-2

ItayGarin/ktrl#32 might be related to this issue.

Add mouse click

This should be more easily cross platform than replicating the whole mouse.

Here's my use case: I have a trackball that is great for scrolling and movement but I don't like it much for clicking. So instead, when paired with my QMK board, I click with my left hand using the keyboard and navigate+scroll with my right hand using the trackball.

Mouse support for scroll and extra buttons

Is it doable for including more mouse support as in default x11.

1 = left button
2 = middle button (pressing the scroll wheel)
3 = right button
4 = turn scroll wheel up
5 = turn scroll wheel down
6 = push scroll wheel left
7 = push scroll wheel right
8 = 4th button (aka browser backward button)
9 = 5th button (aka browser forward button)

Reducing CPU usage

I have an AMD Ryzen 9 3900X 12-core processor, and when left running unchecked, kanata's CPU usage sits at 30%+.

If I use Task Manager to restrict which processors kanata.exe can utilise, the CPU drops down to a negligible 0.x% without any noticeable performance impact (including with the TCP server emitting outgoing and processing incoming messages).

image

I think it would be a good idea to allow the number of processors that kanata utilises to be configurable either via a command line flag or through the configuration file.

Add f13 ~ f23 mapping for kbd configuration

I have the truly ergonomic keyboard which can mapping the keys to F16, ... , F23 to remap.
https://trulyergonomic.com/ergonomic-keyboards/knowledge-base/

When I added 'f22' in the kbd file, kanata makes error like

thread 'kanata' panicked at 'Could not parse cfg: Unknown key in defsrc: "f22"', src\main.rs:85:51
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Any { .. }', src\main.rs:94:20

please add more function keys to find proper OS keys at mod.rs

Thank you for your great program.

Doesn't build on Manjaro ARM

I was able to build kanata on regular x86_64 PC without any issues, but it fails to build on Pinebook Pro under Manjaro ARM. Error is

   Compiling kanata v1.0.1 (/home/fenuks/Projects/keyboard/kanata)
error[E0308]: mismatched types
  --> src/oskbd/linux.rs:91:29
   |
91 |             uidev.name[0] = 'k' as i8;
   |             -------------   ^^^^^^^^^ expected `u8`, found `i8`
   |             |
   |             expected due to the type of this binding

error[E0308]: mismatched types
  --> src/oskbd/linux.rs:92:29
   |
92 |             uidev.name[1] = 't' as i8;
   |             -------------   ^^^^^^^^^ expected `u8`, found `i8`
   |             |
   |             expected due to the type of this binding

error[E0308]: mismatched types
  --> src/oskbd/linux.rs:93:29
   |
93 |             uidev.name[2] = 'r' as i8;
   |             -------------   ^^^^^^^^^ expected `u8`, found `i8`
   |             |
   |             expected due to the type of this binding

error[E0308]: mismatched types
  --> src/oskbd/linux.rs:94:29
   |
94 |             uidev.name[3] = 'l' as i8;
   |             -------------   ^^^^^^^^^ expected `u8`, found `i8`
   |             |
   |             expected due to the type of this binding

For more information about this error, try `rustc --explain E0308`.
error: could not compile `kanata` due to 4 previous errors

Changing these casts to u8 fixes compilation error, so it seems it's portability problem, and c_char on my CPU is u8, as seen in libc sources:

//! AArch64-specific definitions for 64-bit linux-like values

pub type c_char = u8;

I'm not that familiar with rust, but perhaps code should be changed to something to this in order to fix problem for various strange machines:

diff --git i/src/oskbd/linux.rs w/src/oskbd/linux.rs
index a7de646..b3424ae 100644
--- i/src/oskbd/linux.rs
+++ w/src/oskbd/linux.rs
@@ -14,6 +14,7 @@
 use crate::custom_action::*;
 use crate::keys::*;
 use libc::input_event as raw_event;
+use libc::c_char;
 
 // file i/o
 use io::Write;
@@ -88,10 +89,10 @@ pub fn new() -> Result<Self, io::Error> {
             }
 
             let mut uidev: uinput_user_dev = mem::zeroed();
-            uidev.name[0] = 'k' as i8;
-            uidev.name[1] = 't' as i8;
-            uidev.name[2] = 'r' as i8;
-            uidev.name[3] = 'l' as i8;
+            uidev.name[0] = 'k' as c_char;
+            uidev.name[1] = 't' as c_char;
+            uidev.name[2] = 'r' as c_char;
+            uidev.name[3] = 'l' as c_char;
             uidev.id.bustype = 0x3; // BUS_USB
             uidev.id.vendor = 0x1;
             uidev.id.product = 0x1;

Programmatically changing layers

I have a vague idea in my head of being able to programmatically change layers when the focused application changes.

As I mentioned on Reddit, komorebi has an event stream that can be subscribed to and acted upon; the idea I have looks like writing a daemon to respond to FocusChange events from komorebi by triggering LayerChange events in kanata.

The concrete use case I have for this right now is automatically changing to my ff layer for Vim-like navigation in Firefox whenever it takes focus and switching back to my base layer whenever any other application takes focus. I'm sure as I add more and more application-specific layers this sort of functionality would become exponentially more useful and ergonomic for long sessions at the computer.

This feature seems like it could naturally fit into the work that is being done in #44, which the server responding to client messages to trigger layer changes (and maybe other actions in the future?).

Let me know what you think!

behaviour of multi cmd is incorrect

It seems that multi cannot process more than 2 cmd.
For example:
pp (multi q (cmd notify-send "hello") t (cmd notify-send "hi"))
will print qt and display hello without notifying the hi
the same if I put it like this
pp (multi (cmd notify-send "hello") (cmd notify-send "hi")) will process only the first cmd.

When active on Linux

Hi

Just to clarify ... when is this active on Linux?

  1. at boot (to command line) ?
  2. in desktop environment ?

I have my own custom layout, but it's currently only configured in KDE, so to log in I need to know where the Qwerty keys are. Avoiding that would be good.

Thanks, Ian

ralt is sending lctl press

Hello and thank you for working on this.

I have an issue using kanata with windows. If my config (defsrc and deflayer) includes lctl it will send a lctl keypress when I press ralt. Here is the debug log:

10:08:27 [INFO] NOTE: kanata was compiled to never allow cmd
10:08:27 [INFO] Kanata: config parsed
10:08:27 [INFO] Sleeping for 2s. Please release all keys and don't press additional ones.
10:08:27 [INFO] Kanata: entering the processing loop
10:08:27 [INFO] Init: catching only releases and sending immediately
10:08:37 [INFO] Starting kanata proper
10:08:40 [DEBUG] (1) kanata::kanata: event loop: KeyEvent { code: KEY_LEFTCTRL, value: Press }
10:08:40 [DEBUG] (1) kanata::kanata: event loop: KeyEvent { code: KEY_RIGHTALT, value: Press }
10:08:40 [DEBUG] (2) kanata::kanata: press     LCtrl
10:08:40 [DEBUG] (2) kanata::kanata: press     RAlt
10:08:40 [DEBUG] (1) kanata::kanata: event loop: KeyEvent { code: KEY_RIGHTALT, value: Release }
10:08:40 [DEBUG] (2) kanata::kanata: release   RAlt
10:08:54 [DEBUG] (1) kanata::kanata: event loop: KeyEvent { code: KEY_LEFTCTRL, value: Press }
10:08:54 [DEBUG] (2) kanata::kanata: repeat    LCtrl
10:08:54 [DEBUG] (1) kanata::kanata: event loop: KeyEvent { code: KEY_LEFTCTRL, value: Release }
10:08:54 [DEBUG] (2) kanata::kanata: release   LCtrl

What I am doing here is:

  1. Start kanata
  2. Press and hold RAlt
  3. Notice that the left ctrl is "pressed" but not released
  4. Release RAlt
  5. Now the computer behaves as if lctl is pressed
  6. Pressing lctl again releases lctl

Here is my config:

(defcfg
  ;; Windows does not need any input / output config
 )

(defalias
  met_a (tap-hold 200 200 a lmet)
  alt_s (tap-hold 200 200 s lalt)
  ctl_d (tap-hold 200 200 d lctl)
  sft_f (tap-hold 200 200 f lsft)
  sft_j (tap-hold 200 200 j rsft)
  ctl_k (tap-hold 200 200 k rctl)
  alt_l (tap-hold 200 200 l ralt)
  met_; (tap-hold 200 200 ; lmet)
)

(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

(deflayer homerowmods
  grv   1       2       3       4       5       6       7       8       9       0       -     =     bspc
  tab   q       w       e       r       t       y       u       i       o       p       [     ]     \
  caps  @met_a  @alt_s  @ctl_d  @sft_f  g       h       @sft_j  @ctl_k  @alt_l  @met_;  '     ret
  lsft  z       x       c       v       b       n       m       ,       .       /       rsft
  lctl  lmet    lalt                    spc                     ralt    rmet    rctl
)

To get around this issue I can simply remove lctl from my config and everything will work as intended.

Not sure if it matters, but I am using norwegian keyboard layout with Alt Gr as right alt key.

Multiple defcfg linux-dev

I use two of these 6x4 keypad as a split keyboard. As they are two independent keyboards, normally I can't setup layers which works across the "halves" (a key in one keypad which activates a layer in the other one). To solve this I currently use evsieve to fake one device out of these two. This way:

# evsieve --input /dev/input/by-id/usb-BlackC_Sayobot.cn_L-event-kbd grab --input /dev/input/by-id/usb-BlackC_Sayobot.cn_R-event-kbd grab --output create-link=/dev/input/by-id/sayo

It would be nice if kanata could use multiple devices this way out of the box.

H80454abdae6b4f8c9749ffbb733055a5D

Figure out a better workaround for newline repeat on startup

When starting the program, newlines get repeatedly and rapidly sent into the active application until a new key is pressed. This is currently worked around by sending spaces for 1s on program start, but this is pretty ugly. Need to see if there's a better solution.

Gracefully exit

I am trying to add a functionality of creating a symlink in /dev/input/by-id/ for the newly created device /dev/input/eventxx.

Creating a symlink works if #45 is applied. However, kanata doesn't gracefully exit, which makes cleaning up the symlink rather hard if not impossible.

I would like to discuss about graceful exit.

Live reload of configuration

Have a key action for hot reloading the configuration. A ~1-second convenience compared to closing and restarting the application.

Rename layer-toggle to layer-hold

I've had this discussion before in this thread: kmonad/kmonad#560 (comment)

Basically, the main points are:

  • toggle doesn't imply a momentary switch
  • toggle's usage in here contradicts its usage in a lot of applications and games
  • After not looking at your config for a long time, if you look at it again and try to differentiate between layer-switch and layer-toggle, the average user might be initially confused and have to look for the config reference again.

With kmonad, we eventually settled with adding momentary-layer as an alias, but I still think renaming it layer-hold is the more succinct solution because

  • It keeps the layer prefix pattern
  • hold is much simpler and more precise for the average user

The author seems to want to reserve hold for patterns like tap-hold, but I believe the average user would easily differentiate between tap-hold and layer-hold because of the different namespaces/contexts.

Add some way for an external application to receive structured output events from kanata

The code that logs layer changes is:

fn check_handle_layer_change(&mut self) {

A new member could be added to the Kanata struct to hold any server configurations:

let kbd_in_path = cfg

pub struct Kanata {

It probably makes sense to start the server in main_impl, though I haven't thought too hard about:

fn main_impl(cfg: CfgPath) -> Result<()> {

Add support for macros

A macro is different from the current multi action in the configuration because multi keeps all of the keys pressed for the entire duration. This makes some string sequences impossible to type with multi, e.g. http://localhost because : requires shift to type and then shift will be held for the entire duration.

Allow to emit on release only

I'd like a functionality where you can emit a tap on-release only. The expression could be named on-release.

You can get a similar functionality in kmonad with tap-macro-release by ignoring the all the arguments except the last. (Note: To fully copy tap-macro-release, you'd probably just have to combine on-release with multi and macro)

I've found the on-release functionality useful for complex layer switching where I would keep/change a layer depending on which key I release last.

I've also found it useful for clearing modifiers (especially since kmonad has a press-only button that allows to keep mods activated).

Feature request: shell command or workaround

I am really impressed with kanata. It replaced my xcape and kind of my use of kmonad. Tap-hold works well.
I was struggling to get a notification when changing layers , I got this workaround
nnlck ( multi (layer-switch numpad) (macro C-A-S-a))
the chord is binded to a shell notification that numpad is active. So far so good

The only thing that i miss from kmonad is switching out of virtualbox. In kmonad I could do it with a shell command to show the desktop.
kkk (multi-tap 300 (cmd-button "wmctrl -k on") (cmd-button "wmctrl -k off") )
For kanata, using a macro with chording I could not do it since virtualbox took over my keyboard and mouse

Feature request: System tray support

I personally like using kanata without system tray but system tray comes in handy to know if kanata is running or not and on which keyboard(or configuration).
It can be used at a later stage to control multiple keyboards on and of, or improvement in gui configurations.

evdev device resources are not correctly released when kanata is killed by signals

evdev device should call these functions to release resources before closing the device fd. They are wrapped by evdev-rs in the Drop trait.

Currently, the only way to terminate kanata is to kill it by a signal, e.g. SIGINT and SIGTERM.

Rust doesn't unwind and call drop() by default when receive SIGINT and SIGTERM, which causes those devices fail to release resources properly.

Relates to #46 , but I think this should be a separate issue and I cannot re-open that issue.

tap-hold inside tap hold behaves incorrectly

I was trying to fully utilize tap-hold by inserting another tap-hold inside it with no luck
pp (tap-hold 200 200 a (tap-hold 200 2000 b c))
no matter how I hold key, could not get b. it either prints a or c

102d is not working

I have Pinebook Pro with ISO keyboard, and it seems that kanata cannot handle 102d key. With this simple config

(defcfg
  linux-dev /dev/input/by-id/usb-HAILUCK_CO._LTD_USB_KEYBOARD-event-kbd
)

(defsrc
  esc  f1    f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12
  grv  1     2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q     w    e    r    t    y    u    i    o    p    [    ]    ret
  caps a     s    d    f    g    h    j    k    l    ;    '    \
  lsft 102d  z    x    c    v    b    n    m    ,    .    /    rsft            up
  lctl lmet  lalt           spc                 ralt rctl                left down rght
)

(deflayer qwerty
  esc  f1    f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12
  grv  1     2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q     w    e    r    t    y    u    i    o    p    [    ]    ret
  caps a     s    d    f    g    h    j    k    l    ;    '    \
  lsft 102d  z    x    c    v    b    n    m    ,    .    /    rsft            up
  lctl lmet  lalt           spc                 ralt rctl                left down rght
)

all keys work, except for nubs.

kanata prints

19:51:53 [DEBUG] (2) kanata::oskbd::linux: input ev: InputEvent { time: TimeVal { tv_sec: 0, tv_usec: 0 }, event_type: EV_KEY, event_code: EV_KEY(KEY_UNKNOWN), value: 0 }

xev (with kanata disabled):

KeyPress event, serial 39, synthetic NO, window 0x1200001,
    root 0x226, subw 0x0, time 6757247, (-249,402), root:(622,847),
    state 0x0, keycode 94 (keysym 0x3c, less), same_screen YES,
    XLookupString gives 1 bytes: (3c) "<"
    XmbLookupString gives 1 bytes: (3c) "<"
    XFilterEvent returns: False

I've added some prints, and in linux.rs

impl From<KeyCode> for OsCode {
    fn from(item: KeyCode) -> Self {

receives KeyCode::No, and from(item: OsCode) -> KeyCode receives OsCode::KEY_UNKNOWN.

Problem is present under both X11 and Wayland.

Unicode support

Unicode support should be possible in Linux applications with the existing functionality. Holding Ctrl+Shift+u then typing the unicode number will input the unicode character.

E.g. this sad smiley ☹ is U+2639, so the alias below works correctly to input the sad smiley.

(defalias sad (multi lctl lsft u 2 6 3 9))

However, Windows does not have any such convenient and well-designed feature. It looks like kbremap has unicode support for Windows though, so it's definitely possible.

https://github.com/timokroeger/kbremap

Add action for releasing state

Use case:

Let's say I want lalt as a multi-use key that acts as lalt as well as layer-toggle at the same time. Some desired actions in the new layer want lalt to be held down the whole time (1) since repeated press-release of alt results in the wrong behaviour. Other actions (2) actually don't want alt to be pressed at all.

To achieve (1), one could use (multi lalt (layer-toggle other-layer)). To achieve (2), a theoretical action (multi (release lalt) <un-alted key>) could work.

order of log `Kanata: config parsed` can be improved

Kanata: config parsed should be before Created device "/dev/input/event7"

12:57:40 [INFO] Created device "/dev/input/event7"
12:57:40 [INFO] Created symlink "/run/kanata-mykbd/mykbd" -> "/dev/input/event7"
12:57:40 [INFO] Kanata: config parsed
12:57:40 [INFO] Sleeping for 2s. Please release all keys and don't press additional ones.
12:57:42 [INFO] Kanata: entering the processing loop
12:57:42 [INFO] Kanata: entering the event loop
12:57:42 [INFO] Init: catching only releases and sending immediately
12:57:42 [INFO] Starting kanata proper

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.