Mouse movement constant factor/multiplier keys to instantaneously change speed #2206
Description
Background and Use Case
I currently use a fork of ZMK that includes #2027. I use constant-speed mouse/scroll movement (exponent 0, time-to-max 0), which I find much easier to control. The downside is that it's a poor fit for handling both precise movement and large screen movements.
In QMK, I resolved this problem using the different cursor speeds offered by the KC_ACL{0,1,2}
bindings. The cursor had four speeds (including the default, unmodified one) and holding a key for the alternate speed took effect immediately, without moving any of your other fingers or lifting them off their keys.
In the version of mouse movement in #2027 and (I think) #778, it seems like the only way to get different mouse/scroll speeds at different times is to use different keys, possibly on different layers. This is pretty awkward when you're used to using just WASD to move the mouse around, and doubly so if you choose to put those alternate speeds on a different layer -- both methods require lifting and moving the fingers being actively used for the movement, which feels a bit like having multiple gas pedals in your car for different speeds.
If I've misunderstood, and there is a way to get my desired behavior with some clever usage of macros, I'd love to hear it! Composing a solution out of the existing parts is preferable.
Assuming not, here is a proposal. I would be happy to open a PR as well if you think this is a good idea. My fork already has more primitive prototype of this behavior implemented and working.
Proposal: Speed Multiplier Keys
#define
a new type of thing that can be provided to any zmk,behavior-input-two-axis
(but I'll use &mmv
as an example for the rest of this):
&mmv MOVE_MULTIPLIER(2)
This would double the speed of any other &mmv
keys that are held while this key is held. Multipliers would combine... multiplicatively... so if you held more than one such modifier you would get a speedup proportional to their product. This factor would be applied as the last step, after all other acceleration, exponent, etc. math has been performed to compute the current tick's delta x/y.
The lack of floating point (and please correct me if I'm wrong about that) makes defining slower-than-default speeds awkward. Instead of defining a multiplier [0, 1) and being done with it, you could instead define a "base" multiplier that is ignored if other multipliers are active:
&mmv {
base-multiplier = <4>;
};
This means that all speeds are multiplied by 4 by default, unless any other modifiers are held, in which case those held values are used instead. In the case of 4, this means slower speeds could be 1/4, 2/4 or 3/4 of the "base" speed. It also means that the numbers in your keymap have to be 1/4 as large as you think. (This value could be a regular constant instead of a behavior property as well.)
As an implementation detail, it would probably be best to change the underlying two-axis behavior to accept two parameters instead of one. The speeds could remain bit-packed into the first, and the second would be used to communicate the multiplier, if present. The MOVE_X
(etc.) macros would change to hardcode a 0 or sentinel value for the second parameter, so you could still do e.g. &mmv MOVE_X(500)
and it would continue to work.
It seems unlikely that this behavior would be composed with non-linear or non-constant two-axis movement configurations, but it would have well-defined semantics if so.