-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
feat(mouse): Add mouse move and scroll support #2477
base: main
Are you sure you want to change the base?
feat(mouse): Add mouse move and scroll support #2477
Conversation
e90e11d
to
7e9f046
Compare
It looks like there is a bug in ticks->ms conversions in mouse keys that break acceleration behavior; these fixes got acceleration working again for me: diff --git a/app/src/behaviors/behavior_input_two_axis.c b/app/src/behaviors/behavior_input_two_axis.c
index 20f5d52a..dd2f3bf6 100644
--- a/app/src/behaviors/behavior_input_two_axis.c
+++ b/app/src/behaviors/behavior_input_two_axis.c
@@ -112,7 +112,7 @@ static float speed(const struct behavior_input_two_axis_config *config, uint16_t
float max_speed, int64_t duration_ticks) {
uint8_t accel_exp = get_acceleration_exponent(config, code);
- if ((duration_ticks * CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000) > config->time_to_max_speed_ms ||
+ if ((1000 * duration_ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) > config->time_to_max_speed_ms ||
config->time_to_max_speed_ms == 0 || accel_exp == 0) {
return max_speed;
}
@@ -123,8 +123,8 @@ static float speed(const struct behavior_input_two_axis_config *config, uint16_t
return 0;
}
- float time_fraction = (float)duration_ticks * CONFIG_SYS_CLOCK_TICKS_PER_SEC /
- config->time_to_max_speed_ms / 1000;
+ float time_fraction = (float)(1000 * duration_ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC) /
+ config->time_to_max_speed_ms;
return max_speed * powf(time_fraction, accel_exp);
} |
&mmv MOVE_DOWN | ||
``` | ||
|
||
The following will send a scroll left event to the host when pressed/held: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"scroll" should be "mouse move" here and in line 90, I think.
2052d19
to
4fc6861
Compare
4fed437
to
d1a09bb
Compare
d1a09bb
to
447afcb
Compare
just fyi, I used this in a custom build and it seems to be working just fine, thanks! https://github.com/kaievns/little-wing/blob/6ce99b4b3827adb583cbbd0d54b5616a0b304c66/zmk-config/config/little_wing.keymap#L27C1-L44C7 a built in mouse to wheel mapper would be a good idea I reckon, i stole mine from badjeff's work |
I added a preconfigured code mapper for this today. After |
I've just given it a go and it works perfectly for me. I've also noticed that you've added the two-axis to mouse scroll |
a6cb056
to
032f421
Compare
I was using your previous branch, and I switched to this one. So far it's working great for me with just basic mouse move emulation and scroll on the key bindings. However, the speed of the scroll is wickedly fast compared to the scrolling speed on your previous branch. Almost too quick to keep up with in most cases. |
@petejohanson |
hey @petejohanson i think there is something fishy going on with the Long story short I'm building a split keyboard with a trackball and I followed your work that someone in discord pointed me to over here https://github.com/sadekbaroudi/zmk-fingerpunch-vik/pull/1/files and i have adopted it over here https://github.com/kaievns/little-wing/blob/6aaabf9901a5721276f37030116f5688fcd68fa0/zmk-config/boards/shields/little_wing/little_wing_right.overlay#L11-L35 If I set the left side as central and the right one (the one with a trackball) as a periferal side, it compiles and works great via USB, but in case of bluetooth connection I think there is lag + interference as data is fed from right to left and then to a PC, and that leads to some very jumpy and unstable cursor movements. And kind of unusable tbh. But, if i try to set the right side as the central one--so that data would go straight to the PC--, it doesn't compile. The left side says that the
and the right side compiles but fails at the linking stage
which looks like some sort of device ordering issue. thought I'd share it, feel free to ping me on discord if you'd want to dig into it |
This is a great update; simple to implement, the scrolling is fantastic -- so smooth! Is there a way to specify cursor speed? Also, are there any options for acceleration such as ramping up to full speed after X ms? |
f6967ba
to
8e7687c
Compare
* Use Zephyr input subsystem for all pointers. * Input processors for modifying events, e.g. scaling, swapping codes, temporary (mouse) layers, etc. * Mouse move/scroll behaviors. * Infrastructure in place for physical pointer input devices. Co-authored-by: Alexander Krikun <[email protected]> Co-authored-by: Robert U <[email protected]> Co-authored-by: Shawn Meier <[email protected]>
* Drop the default scroll value again. In theory you only want the higher value *IF* you enable the smooth scrolling Kconfig setting.
7462515
to
ab5aadb
Compare
Co-authored-by: Anant Thazhemadam <[email protected]>
|
||
### Shared | ||
|
||
Both peripheral and central make use of a `zmk,input-split` device, which functions differently depending on where is is used. To avoid duplicating work, this node can be defined in a common `.dtsi` file that is included into both central and peripheral `.overlay`/`.dts` files. Second, the input listener for the central side is added here, but disabled, so that keymaps (which are included for central and peripheral builds) can reference the listener to add input processors without issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both peripheral and central make use of a `zmk,input-split` device, which functions differently depending on where is is used. To avoid duplicating work, this node can be defined in a common `.dtsi` file that is included into both central and peripheral `.overlay`/`.dts` files. Second, the input listener for the central side is added here, but disabled, so that keymaps (which are included for central and peripheral builds) can reference the listener to add input processors without issue. | |
Both peripheral and central make use of a `zmk,input-split` device, which functions differently depending on where it is used. To avoid duplicating work, this node can be defined in a common `.dtsi` file that is included into both central and peripheral `.overlay`/`.dts` files. Second, the input listener for the central side is added here, but disabled, so that keymaps (which are included for central and peripheral builds) can reference the listener to add input processors without issue. |
|
||
static int code_idx(uint16_t code, const uint16_t *list, size_t len) { | ||
for (int i = 0; i < len; i++) { | ||
if (list[0] == code) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be comparing the list entry at the index
if (list[0] == code) { | |
if (list[i] == code) { |
Summary
This is the planned successor to #2027 that integrates a more flexible input processing system inspired by the work by badjeff. I will leave #2027 alone for now, but this PR is intended to be the version that's targeted to actually merge.
WARNING The work in this PR is subject to ZERO API/code/config stability guarantees. If you want something that won't randomly break on you, keep using #2027. Only use the branch from this PR if you are willing to accept that, follow the PR closely for any changes, and are technical enough to solve any problems that occur from using it.
Input Processors
All the options for scaling, swapping X/Y values, etc are now accomplished with input processors, that can be set on a given listener, and overridden for a set of given layers:
I've implemented input processors with the following compatible values:
zmk,input-processor-code-mapper
- For translating input codes to other values. Useful for enabling a "scroll layer" that makes a pointer send scroll events instead of X/Y move events.zmk,input-processor-scaler
- For scaling values, using a passed in multiplier and divisor. Useful for "precision layer". Example&vip_xy_scaler 1 4
to scale values by 1/4, for fine grained movements.zmk,input-processor-temp-layer
- For enabling a layer until a certain time period of no input events from the device. Useful for a "mouse layer" with mouse keys when using an integrated trackpad/ball/whatever.zmk,input-processor-transform
- For swapping X/Y values, inverting a given Y or X value. Useful when a given input driver doesn't support these transforms and it may be installed rotated 90deg, etc.Input processors are tied to input listeners, with layer overrides, e.g.:
Smooth Scrolling
This also adds "smooth scrolling" support, by using HID "resolution multipliers", which appears to be supported in Linux and Windows, but not macOS. On macOS, we should be properly falling back to normal behavior here even with
CONFIG_ZMK_MOUSE_SMOOTH_SCROLLING=y
. More testing needed here.Split
This PR includes a second commit to add split input device support. You can see an example PR implementing a split Cirque controller at sadekbaroudi/zmk-fingerpunch-vik#1
The key new driver here is behind the
zmk,input-split
compatible value. This driver has different modes based on being used on a split peripheral or central. When used on a peripheral, this acts as a listener for the specified input events on the referenced device, and forwards those events to the central (after some optional peripheral side input processing that can be used to clean up rotation, etc. beforehand). On the central, this driver registeres it's own input device, that should have a ZMK input listener added referencing it. The driver will receive the events from the peripheral and fire them locally for processing.Testing
So far, I've tested with mouse keys/scroll/move, and with a Cirque device. More testing all around! Existing generic Zephyr input devices should still "just work" with this PR.
To Do
/omit-if-no-ref/
.