24 comments

[ 3.1 ms ] story [ 64.4 ms ] thread
If you're on xorg you could just configure pointerkeys https://wiki.gentoo.org/wiki/Xorg/Using_the_numeric_keyboard...
If you've got a keyboard with QMK firmware, and mousekeys were enabled for it... you can just turn it on with https://www.caniusevia.com/ . One of my machines didn't have a mouse, so my next keyboard was a Keychron Q2 https://www.keychron.com/products/keychron-q2-qmk-custom-mec... - I thought I was going to have to recompile the firmware for this but it's already on: https://github.com/Keychron/qmk_firmware/blob/master/keyboar...

...you just need to map keys. It was very easy, so now fn-arrow and fn-return work as a mouse on anything I've attached it to so far. I got an rpi recently, only connected this, and was able to navigate the startup ui with no mouse.

works on ZMK firmware too just not the main repo, but one of the forks mentioned in the main repo.

the advantage with this is that it's cross platform.

I think the biggest disadvantage to "do it in firmware" is it requires an external keyboard. (& the good ones which let your thumbs use more than one key are more expensive or diy).

Using the keyboard to drive the mouse isn't a nice experience. -- But, it's nice to have in situations like "I use a bluetooth mouse, on desktop, and bluetooth isn't set up/working". I've found that useful for live ISOs.

I wish my HHKB supported numpad keys without needing an OS tool like AutoHotkey.
And you're probably on xorg if you're following these instructions because wayland only supports libinput.
This is not how I imagine "turning a keyboard into a mouse" to behave. How is this even practically useful? A better solution is to hold a combination of meta keys like ctrl-shift-alt or the like with one hand and use the keyboard like a trackpad with the other, except by "sliding" the keys while they are pressed since almost all keyboards are not touch sensitive. This of course would work best with flatter keys and not mechanical ones.
Either I am completely misunderstanding you, or what you're saying sounds absolutely horrible and unusable to me.

Are you saying you that you would hold some modifier combo and then slide your finger over g,h,j,k,l to go right? How is that anymore usable? You're doing so much movement you may as well just reach for a mouse or touchpad. Also I have no idea how you'd calibrate that to move a sensible amount across short/long distances.

Or are you suggesting something else? I don't understand what you mean by "sliding".

I also enjoyed using https://github.com/rvaiya/warpd on my mac. But was hit with few bugs, where the pointer used to get stuck. Had to keep restarting. But still a nice program to ditch mouse.
I use it all the time, on Ubuntu. Works well, and definitely avoids many keyboard-mouse back-and-forths for 90% of my single clicks.
Very nice insight into libevdev and x programming!
The friction/acceleration awkwardness can be solved by using a physically based timestep-independent formulation, which I implemented in TPMouse[0] and explained its derivation in a previous comment reply[1].

The gist of it is that the solution to a linearly damped particle is a linear system, so the x and y components can be calculated completely independently and the analytic solution is just an exponential of time.

It is a special case of the timestep-independent damped harmonic oscillator, which I previously wrote a blogpost about [10].

Namely it is the "unsprung" special case under "Overdamped"

The very same formulation is also what I used to implement LibreScroll[11] to add inertial scrolling to any mouse.

[0] https://github.com/EsportToys/TPMouse

[1] https://www.reddit.com/r/Trackballs/comments/ym9q2t/tpmouse_...

[10] https://news.ycombinator.com/item?id=35899215

[11] https://news.ycombinator.com/item?id=36783942

The Amiga used to do this, I think it was Amiga Key + arrows.
Nice! libevdev is really good, any reason why this is implemented using a thread? I would have love to see how this was implemented asynchronous in C.
Thanks! A thread was just easier for me to reason about. If we wanted to do this all in one thread, we could have the main loop use a system where it keeps track of how often it needs to poll the input and how often it needs to generate mouse events, and waits for the soonest deadline for each.