From 3cd2a27ac0f963bc2023c3004f6f8eff0eb62a81 Mon Sep 17 00:00:00 2001 From: francislan Date: Fri, 13 Mar 2020 09:49:44 -0700 Subject: [PATCH] Decouple mouse cursor and mouse wheel in accelerated mode (#6685) * Decouples mouse cursor and mouse wheel movements in accelerated mode. * Fixed comment indentation. * Updated docs Co-authored-by: Francis LAN --- docs/feature_mouse_keys.md | 3 ++ tmk_core/common/mousekey.c | 72 +++++++++++++++++++++++++------------- tmk_core/common/mousekey.h | 6 ++++ 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md index 363662f63..88a2c7c05 100644 --- a/docs/feature_mouse_keys.md +++ b/docs/feature_mouse_keys.md @@ -58,6 +58,8 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u |`MOUSEKEY_INTERVAL` |50 |Time between cursor movements | |`MOUSEKEY_MAX_SPEED` |10 |Maximum cursor speed at which acceleration stops | |`MOUSEKEY_TIME_TO_MAX` |20 |Time until maximum cursor speed is reached | +|`MOUSEKEY_WHEEL_DELAY` |300 |Delay between pressing a wheel key and wheel movement | +|`MOUSEKEY_WHEEL_INTERVAL` |100 |Time between wheel movements | |`MOUSEKEY_WHEEL_MAX_SPEED` |8 |Maximum number of scroll steps per scroll action | |`MOUSEKEY_WHEEL_TIME_TO_MAX`|40 |Time until maximum scroll speed is reached | @@ -66,6 +68,7 @@ Tips: * Setting `MOUSEKEY_DELAY` too low makes the cursor unresponsive. Setting it too high makes small movements difficult. * For smoother cursor movements, lower the value of `MOUSEKEY_INTERVAL`. If the refresh rate of your display is 60Hz, you could set it to `16` (1/60). As this raises the cursor speed significantly, you may want to lower `MOUSEKEY_MAX_SPEED`. * Setting `MOUSEKEY_TIME_TO_MAX` or `MOUSEKEY_WHEEL_TIME_TO_MAX` to `0` will disable acceleration for the cursor or scrolling respectively. This way you can make one of them constant while keeping the other accelerated, which is not possible in constant speed mode. +* Setting `MOUSEKEY_WHEEL_INTERVAL` too low will make scrolling too fast. Setting it too high will make scrolling too slow when the wheel key is held down. Cursor acceleration uses the same algorithm as the X Window System MouseKeysAccel feature. You can read more about it [on Wikipedia](https://en.wikipedia.org/wiki/Mouse_keys). diff --git a/tmk_core/common/mousekey.c b/tmk_core/common/mousekey.c index 2df7728a4..00357f5f6 100644 --- a/tmk_core/common/mousekey.c +++ b/tmk_core/common/mousekey.c @@ -39,6 +39,9 @@ static uint16_t last_timer = 0; #ifndef MK_3_SPEED +static uint16_t last_timer_c = 0; +static uint16_t last_timer_w = 0; + /* * Mouse keys acceleration algorithm * http://en.wikipedia.org/wiki/Mouse_keys @@ -56,6 +59,10 @@ uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX; /* ramp used to reach maximum pointer speed (NOT SUPPORTED) */ // int8_t mk_curve = 0; /* wheel params */ +/* milliseconds between the initial key press and first repeated motion event (0-2550) */ +uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10; +/* milliseconds between repeated motion events (0-255) */ +uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL; uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; @@ -96,33 +103,48 @@ static uint8_t wheel_unit(void) { } void mousekey_task(void) { - if (timer_elapsed(last_timer) < (mousekey_repeat ? mk_interval : mk_delay * 10)) { - return; - } - if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0) { - return; - } - if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; - if (mouse_report.x > 0) mouse_report.x = move_unit(); - if (mouse_report.x < 0) mouse_report.x = move_unit() * -1; - if (mouse_report.y > 0) mouse_report.y = move_unit(); - if (mouse_report.y < 0) mouse_report.y = move_unit() * -1; - /* diagonal move [1/sqrt(2)] */ - if (mouse_report.x && mouse_report.y) { - mouse_report.x = times_inv_sqrt2(mouse_report.x); - if (mouse_report.x == 0) { - mouse_report.x = 1; - } - mouse_report.y = times_inv_sqrt2(mouse_report.y); - if (mouse_report.y == 0) { - mouse_report.y = 1; + // report cursor and scroll movement independently + report_mouse_t const tmpmr = mouse_report; + if ((mouse_report.x || mouse_report.y) && + timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { + if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; + mouse_report.v = 0; + mouse_report.h = 0; + if (mouse_report.x > 0) mouse_report.x = move_unit(); + if (mouse_report.x < 0) mouse_report.x = move_unit() * -1; + if (mouse_report.y > 0) mouse_report.y = move_unit(); + if (mouse_report.y < 0) mouse_report.y = move_unit() * -1; + /* diagonal move [1/sqrt(2)] */ + if (mouse_report.x && mouse_report.y) { + mouse_report.x = times_inv_sqrt2(mouse_report.x); + if (mouse_report.x == 0) { mouse_report.x = 1; } + mouse_report.y = times_inv_sqrt2(mouse_report.y); + if (mouse_report.y == 0) { mouse_report.y = 1; } } + mousekey_send(); + last_timer_c = last_timer; + mouse_report = tmpmr; + } + if ((mouse_report.v || mouse_report.h) && + timer_elapsed(last_timer_w) > (mousekey_repeat ? mk_wheel_interval: mk_wheel_delay * 10)) { + if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; + mouse_report.x = 0; + mouse_report.y = 0; + if (mouse_report.v > 0) mouse_report.v = wheel_unit(); + if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1; + if (mouse_report.h > 0) mouse_report.h = wheel_unit(); + if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1; + /* diagonal move [1/sqrt(2)] */ + if (mouse_report.v && mouse_report.h) { + mouse_report.v = times_inv_sqrt2(mouse_report.v); + if (mouse_report.v == 0) { mouse_report.v = 1; } + mouse_report.h = times_inv_sqrt2(mouse_report.h); + if (mouse_report.h == 0) { mouse_report.h = 1; } + } + mousekey_send(); + last_timer_w = last_timer; + mouse_report = tmpmr; } - if (mouse_report.v > 0) mouse_report.v = wheel_unit(); - if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1; - if (mouse_report.h > 0) mouse_report.h = wheel_unit(); - if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1; - mousekey_send(); } void mousekey_on(uint8_t code) { diff --git a/tmk_core/common/mousekey.h b/tmk_core/common/mousekey.h index 48946987c..05e453823 100644 --- a/tmk_core/common/mousekey.h +++ b/tmk_core/common/mousekey.h @@ -55,6 +55,12 @@ along with this program. If not, see . # ifndef MOUSEKEY_TIME_TO_MAX # define MOUSEKEY_TIME_TO_MAX 20 # endif +# ifndef MOUSEKEY_WHEEL_DELAY +# define MOUSEKEY_WHEEL_DELAY 300 +# endif +# ifndef MOUSEKEY_WHEEL_INTERVAL +# define MOUSEKEY_WHEEL_INTERVAL 100 +# endif # ifndef MOUSEKEY_WHEEL_MAX_SPEED # define MOUSEKEY_WHEEL_MAX_SPEED 8 # endif