aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/feature_mouse_keys.md28
-rw-r--r--tmk_core/common/mousekey.c82
-rw-r--r--tmk_core/common/mousekey.h37
3 files changed, 144 insertions, 3 deletions
diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md
index ffde13389..a0d02416f 100644
--- a/docs/feature_mouse_keys.md
+++ b/docs/feature_mouse_keys.md
@@ -42,6 +42,7 @@ In your keymap you can use the following keycodes to map key presses to mouse ac
42Mouse keys supports three different modes to move the cursor: 42Mouse keys supports three different modes to move the cursor:
43 43
44* **Accelerated (default):** Holding movement keys accelerates the cursor until it reaches its maximum speed. 44* **Accelerated (default):** Holding movement keys accelerates the cursor until it reaches its maximum speed.
45* **Kinetic:** Holding movement keys accelerates the cursor with its speed following a quadratic curve until it reaches its maximum speed.
45* **Constant:** Holding movement keys moves the cursor at constant speeds. 46* **Constant:** Holding movement keys moves the cursor at constant speeds.
46* **Combined:** Holding movement keys accelerates the cursor until it reaches its maximum speed, but holding acceleration and movement keys simultaneously moves the cursor at constant speeds. 47* **Combined:** Holding movement keys accelerates the cursor until it reaches its maximum speed, but holding acceleration and movement keys simultaneously moves the cursor at constant speeds.
47 48
@@ -56,7 +57,8 @@ This is the default mode. You can adjust the cursor and scrolling acceleration u
56|Define |Default|Description | 57|Define |Default|Description |
57|----------------------------|-------|---------------------------------------------------------| 58|----------------------------|-------|---------------------------------------------------------|
58|`MOUSEKEY_DELAY` |300 |Delay between pressing a movement key and cursor movement| 59|`MOUSEKEY_DELAY` |300 |Delay between pressing a movement key and cursor movement|
59|`MOUSEKEY_INTERVAL` |50 |Time between cursor movements | 60|`MOUSEKEY_INTERVAL` |50 |Time between cursor movements in milliseconds |
61|`MOUSEKEY_MOVE_DELTA` |5 |Step size |
60|`MOUSEKEY_MAX_SPEED` |10 |Maximum cursor speed at which acceleration stops | 62|`MOUSEKEY_MAX_SPEED` |10 |Maximum cursor speed at which acceleration stops |
61|`MOUSEKEY_TIME_TO_MAX` |20 |Time until maximum cursor speed is reached | 63|`MOUSEKEY_TIME_TO_MAX` |20 |Time until maximum cursor speed is reached |
62|`MOUSEKEY_WHEEL_DELAY` |300 |Delay between pressing a wheel key and wheel movement | 64|`MOUSEKEY_WHEEL_DELAY` |300 |Delay between pressing a wheel key and wheel movement |
@@ -73,6 +75,30 @@ Tips:
73 75
74Cursor 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). 76Cursor 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).
75 77
78### Kinetic Mode
79
80This is an extension of the accelerated mode. The kinetic mode uses a quadratic curve on the cursor speed which allows precise movements at the beginning and allows to cover large distances by increasing cursor speed quickly thereafter. You can adjust the cursor and scrolling acceleration using the following settings in your keymap’s `config.h` file:
81
82|Define |Default |Description |
83|--------------------------------------|---------|---------------------------------------------------------------|
84|`MK_KINETIC_SPEED` |undefined|Enable kinetic mode |
85|`MOUSEKEY_DELAY` |8 |Delay between pressing a movement key and cursor movement |
86|`MOUSEKEY_INTERVAL` |8 |Time between cursor movements in milliseconds |
87|`MOUSEKEY_MOVE_DELTA` |25 |Step size for accelerating from initial to base speed |
88|`MOUSEKEY_INITIAL_SPEED` |100 |Initial speed of the cursor in pixel per second |
89|`MOUSEKEY_BASE_SPEED` |1000 |Maximum cursor speed at which acceleration stops |
90|`MOUSEKEY_DECELERATED_SPEED` |400 |Decelerated cursor speed |
91|`MOUSEKEY_ACCELERATED_SPEED` |3000 |Accelerated cursor speed |
92|`MOUSEKEY_WHEEL_INITIAL_MOVEMENTS` |16 |Initial number of movements of the mouse wheel |
93|`MOUSEKEY_WHEEL_BASE_MOVEMENTS` |32 |Maximum number of movements at which acceleration stops |
94|`MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS`|48 |Accelerated wheel movements |
95|`MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS`|8 |Decelerated wheel movements |
96
97Tips:
98
99* The smoothness of the cursor movement depends on the `MOUSEKEY_INTERVAL` setting. The shorter the interval is set the smoother the movement will be. Setting the value too low makes the cursor unresponsive. Lower settings are possible if the micro processor is fast enough. For example: At an interval of `8` milliseconds, `125` movements per second will be initiated. With a base speed of `1000` each movement will move the cursor by `8` pixels.
100* Mouse wheel movements are implemented differently from cursor movements. While it's okay for the cursor to move multiple pixels at once for the mouse wheel this would lead to jerky movements. Instead, the mouse wheel operates at step size `1`. Setting mouse wheel speed is done by adjusting the number of wheel movements per second.
101
76### Constant mode 102### Constant mode
77 103
78In this mode you can define multiple different speeds for both the cursor and the mouse wheel. There is no acceleration. `KC_ACL0`, `KC_ACL1` and `KC_ACL2` change the cursor and scroll speed to their respective setting. 104In this mode you can define multiple different speeds for both the cursor and the mouse wheel. There is no acceleration. `KC_ACL0`, `KC_ACL1` and `KC_ACL2` change the cursor and scroll speed to their respective setting.
diff --git a/tmk_core/common/mousekey.c b/tmk_core/common/mousekey.c
index ef18bcf1a..697e0692c 100644
--- a/tmk_core/common/mousekey.c
+++ b/tmk_core/common/mousekey.c
@@ -36,6 +36,9 @@ static void mousekey_debug(void);
36static uint8_t mousekey_accel = 0; 36static uint8_t mousekey_accel = 0;
37static uint8_t mousekey_repeat = 0; 37static uint8_t mousekey_repeat = 0;
38static uint8_t mousekey_wheel_repeat = 0; 38static uint8_t mousekey_wheel_repeat = 0;
39#ifdef MK_KINETIC_SPEED
40static uint16_t mouse_timer = 0;
41#endif
39 42
40#ifndef MK_3_SPEED 43#ifndef MK_3_SPEED
41 44
@@ -43,7 +46,7 @@ static uint16_t last_timer_c = 0;
43static uint16_t last_timer_w = 0; 46static uint16_t last_timer_w = 0;
44 47
45/* 48/*
46 * Mouse keys acceleration algorithm 49 * Mouse keys acceleration algorithm
47 * http://en.wikipedia.org/wiki/Mouse_keys 50 * http://en.wikipedia.org/wiki/Mouse_keys
48 * 51 *
49 * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000) 52 * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
@@ -105,6 +108,69 @@ static uint8_t wheel_unit(void) {
105} 108}
106 109
107# else /* #ifndef MK_COMBINED */ 110# else /* #ifndef MK_COMBINED */
111# ifndef MK_KINETIC_SPEED
112
113/*
114 * Kinetic movement acceleration algorithm
115 *
116 * current speed = I + A * T/50 + A * 0.5 * T^2 | maximum B
117 *
118 * T: time since the mouse movement started
119 * E: mouse events per second (set through MOUSEKEY_INTERVAL, UHK sends 250, the
120 * pro micro on my Signum 3.0 sends only 125!)
121 * I: initial speed at time 0
122 * A: acceleration
123 * B: base mouse travel speed
124 */
125const uint16_t mk_accelerated_speed = MOUSEKEY_ACCELERATED_SPEED;
126const uint16_t mk_base_speed = MOUSEKEY_BASE_SPEED;
127const uint16_t mk_decelerated_speed = MOUSEKEY_DECELERATED_SPEED;
128const uint16_t mk_initial_speed = MOUSEKEY_INITIAL_SPEED;
129
130static uint8_t move_unit(void) {
131 float speed = mk_initial_speed;
132
133 if (mousekey_accel & ((1<<0) | (1<<2))) {
134 speed = mousekey_accel & (1<<2) ? mk_accelerated_speed : mk_decelerated_speed;
135 } else if (mousekey_repeat && mouse_timer) {
136 const float time_elapsed = timer_elapsed(mouse_timer) / 50;
137 speed = mk_initial_speed +
138 MOUSEKEY_MOVE_DELTA * time_elapsed +
139 MOUSEKEY_MOVE_DELTA * 0.5 * time_elapsed * time_elapsed;
140
141 speed = speed > mk_base_speed ? mk_base_speed : speed;
142 }
143
144 /* convert speed to USB mouse speed 1 to 127 */
145 speed = (uint8_t)(speed / (1000.0f / mk_interval));
146 speed = speed < 1 ? 1 : speed;
147
148 return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed;
149}
150
151float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
152
153static uint8_t wheel_unit(void) {
154 float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
155
156 if (mousekey_accel & ((1<<0) | (1<<2))) {
157 speed = mousekey_accel & (1<<2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS;
158 } else if (mousekey_repeat && mouse_timer) {
159 if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) {
160 const float time_elapsed = timer_elapsed(mouse_timer) / 50;
161 speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS +
162 1 * time_elapsed +
163 1 * 0.5 * time_elapsed * time_elapsed;
164 }
165 speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed;
166 }
167
168 mk_wheel_interval = 1000.0f / speed;
169
170 return 1;
171}
172
173# else /* #ifndef MK_KINETIC_SPEED */
108 174
109static uint8_t move_unit(void) { 175static uint8_t move_unit(void) {
110 uint16_t unit; 176 uint16_t unit;
@@ -142,6 +208,7 @@ static uint8_t wheel_unit(void) {
142 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); 208 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
143} 209}
144 210
211# endif /* #ifndef MK_KINETIC_SPEED */
145# endif /* #ifndef MK_COMBINED */ 212# endif /* #ifndef MK_COMBINED */
146 213
147void mousekey_task(void) { 214void mousekey_task(void) {
@@ -193,6 +260,12 @@ void mousekey_task(void) {
193} 260}
194 261
195void mousekey_on(uint8_t code) { 262void mousekey_on(uint8_t code) {
263#ifdef MK_KINETIC_SPEED
264 if (mouse_timer == 0) {
265 mouse_timer = timer_read();
266 }
267#endif /* #ifdef MK_KINETIC_SPEED */
268
196 if (code == KC_MS_UP) 269 if (code == KC_MS_UP)
197 mouse_report.y = move_unit() * -1; 270 mouse_report.y = move_unit() * -1;
198 else if (code == KC_MS_DOWN) 271 else if (code == KC_MS_DOWN)
@@ -260,7 +333,12 @@ void mousekey_off(uint8_t code) {
260 mousekey_accel &= ~(1 << 1); 333 mousekey_accel &= ~(1 << 1);
261 else if (code == KC_MS_ACCEL2) 334 else if (code == KC_MS_ACCEL2)
262 mousekey_accel &= ~(1 << 2); 335 mousekey_accel &= ~(1 << 2);
263 if (mouse_report.x == 0 && mouse_report.y == 0) mousekey_repeat = 0; 336 if (mouse_report.x == 0 && mouse_report.y == 0) {
337 mousekey_repeat = 0;
338#ifdef MK_KINETIC_SPEED
339 mouse_timer = 0;
340#endif /* #ifdef MK_KINETIC_SPEED */
341 }
264 if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0; 342 if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0;
265} 343}
266 344
diff --git a/tmk_core/common/mousekey.h b/tmk_core/common/mousekey.h
index 05e453823..703854b82 100644
--- a/tmk_core/common/mousekey.h
+++ b/tmk_core/common/mousekey.h
@@ -38,16 +38,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
38# endif 38# endif
39 39
40# ifndef MOUSEKEY_MOVE_DELTA 40# ifndef MOUSEKEY_MOVE_DELTA
41#ifndef MK_KINETIC_SPEED
41# define MOUSEKEY_MOVE_DELTA 5 42# define MOUSEKEY_MOVE_DELTA 5
43#else
44# define MOUSEKEY_MOVE_DELTA 25
45#endif
42# endif 46# endif
43# ifndef MOUSEKEY_WHEEL_DELTA 47# ifndef MOUSEKEY_WHEEL_DELTA
44# define MOUSEKEY_WHEEL_DELTA 1 48# define MOUSEKEY_WHEEL_DELTA 1
45# endif 49# endif
46# ifndef MOUSEKEY_DELAY 50# ifndef MOUSEKEY_DELAY
51#ifndef MK_KINETIC_SPEED
47# define MOUSEKEY_DELAY 300 52# define MOUSEKEY_DELAY 300
53#else
54# define MOUSEKEY_DELAY 8
55#endif
48# endif 56# endif
49# ifndef MOUSEKEY_INTERVAL 57# ifndef MOUSEKEY_INTERVAL
58#ifndef MK_KINETIC_SPEED
50# define MOUSEKEY_INTERVAL 50 59# define MOUSEKEY_INTERVAL 50
60#else
61# define MOUSEKEY_INTERVAL 8
62#endif
51# endif 63# endif
52# ifndef MOUSEKEY_MAX_SPEED 64# ifndef MOUSEKEY_MAX_SPEED
53# define MOUSEKEY_MAX_SPEED 10 65# define MOUSEKEY_MAX_SPEED 10
@@ -68,6 +80,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
68# define MOUSEKEY_WHEEL_TIME_TO_MAX 40 80# define MOUSEKEY_WHEEL_TIME_TO_MAX 40
69# endif 81# endif
70 82
83#ifndef MOUSEKEY_INITIAL_SPEED
84#define MOUSEKEY_INITIAL_SPEED 100
85#endif
86#ifndef MOUSEKEY_BASE_SPEED
87#define MOUSEKEY_BASE_SPEED 1000
88#endif
89#ifndef MOUSEKEY_DECELERATED_SPEED
90#define MOUSEKEY_DECELERATED_SPEED 400
91#endif
92#ifndef MOUSEKEY_ACCELERATED_SPEED
93#define MOUSEKEY_ACCELERATED_SPEED 3000
94#endif
95#ifndef MOUSEKEY_WHEEL_INITIAL_MOVEMENTS
96#define MOUSEKEY_WHEEL_INITIAL_MOVEMENTS 16
97#endif
98#ifndef MOUSEKEY_WHEEL_BASE_MOVEMENTS
99#define MOUSEKEY_WHEEL_BASE_MOVEMENTS 32
100#endif
101#ifndef MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS
102#define MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS 48
103#endif
104#ifndef MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS
105#define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8
106#endif
107
71#else /* #ifndef MK_3_SPEED */ 108#else /* #ifndef MK_3_SPEED */
72 109
73# ifndef MK_C_OFFSET_UNMOD 110# ifndef MK_C_OFFSET_UNMOD