aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Arintok <Jon.Arintok@Gmail.com>2019-03-27 04:34:33 +0200
committerDrashna Jaelre <drashna@live.com>2019-03-26 19:34:33 -0700
commit346cbd88167e8e9a979517bf51144ff66e904f01 (patch)
tree292013c351b0d374edae6a7024b93bfe4f4c9f47
parent509668ca7ce224a389a2caa3ff4df19302d4efc1 (diff)
downloadqmk_firmware-346cbd88167e8e9a979517bf51144ff66e904f01.tar.gz
qmk_firmware-346cbd88167e8e9a979517bf51144ff66e904f01.zip
Add 3 speed mousekey movement option (#2246)
This allows for constant, non-accelerated mouse movement, while retaining the original functionality. Configurable by a define.
-rw-r--r--docs/feature_mouse_keys.md107
-rw-r--r--tmk_core/common/mousekey.c372
-rw-r--r--tmk_core/common/mousekey.h56
3 files changed, 360 insertions, 175 deletions
diff --git a/docs/feature_mouse_keys.md b/docs/feature_mouse_keys.md
index 673eafaef..e64ddf3d0 100644
--- a/docs/feature_mouse_keys.md
+++ b/docs/feature_mouse_keys.md
@@ -1,48 +1,48 @@
1# Mousekeys 1# Mousekeys
2 2
3 3
4Mousekeys is a feature that allows you to emulate a mouse using your keyboard. You can move the pointer around, click up to 5 buttons, and even scroll in all 4 directions. QMK 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). 4Mousekeys is a feature that allows you to emulate a mouse using your keyboard. You can move the pointer around, click up to 5 buttons, and even scroll in all 4 directions.
5 5
6## Adding Mousekeys to a Keymap 6There are 2 ways to define how the mousekeys behave, using "[auto-accelerating](#configuring-the-behavior-of-mousekeys-with-auto-accelerated-movement)" or "[3-speed constant](#configuring-the-behavior-of-mousekeys-with-3-speed-constant-movement)" behavior.
7 7
8There are two steps to adding Mousekeys support to your keyboard. You must enable support in the `rules.mk` file and you must map mouse actions to keys on your keyboard. 8In either case, you will need to enable mousekeys in your makefile,
9and add the relevant [keycodes](#mapping-mouse-actions-to-keyboard-keys) to your keymap.
9 10
10### Adding Mousekeys Support in the `rules.mk` 11#### Enable Mousekeys
11 12
12To add support for Mousekeys you simply need to add a single line to your keymap's `rules.mk`: 13To enable the mousekey functionality, add the following line to your keymap's `rules.mk`:
13 14
14``` 15```
15MOUSEKEY_ENABLE = yes 16MOUSEKEY_ENABLE = yes
16``` 17```
17 18
18You can see an example here: https://github.com/qmk/qmk_firmware/blob/master/keyboards/clueboard/66/keymaps/mouse_keys/rules.mk 19#### Mapping Mouse Actions to Keyboard Keys
19
20### Mapping Mouse Actions to Keyboard Keys
21 20
22You can use these keycodes within your keymap to map button presses to mouse actions: 21You can use these keycodes within your keymap to map button presses to mouse actions:
23 22
24|Key |Aliases |Description | 23|Key |Aliases |Description |
25|----------------|---------|---------------------------| 24|----------------|---------|-----------------------------------|
26|`KC_MS_UP` |`KC_MS_U`|Mouse Cursor Up | 25|`KC_MS_UP` |`KC_MS_U`|Mouse Cursor Up |
27|`KC_MS_DOWN` |`KC_MS_D`|Mouse Cursor Down | 26|`KC_MS_DOWN` |`KC_MS_D`|Mouse Cursor Down |
28|`KC_MS_LEFT` |`KC_MS_L`|Mouse Cursor Left | 27|`KC_MS_LEFT` |`KC_MS_L`|Mouse Cursor Left |
29|`KC_MS_RIGHT` |`KC_MS_R`|Mouse Cursor Right | 28|`KC_MS_RIGHT` |`KC_MS_R`|Mouse Cursor Right |
30|`KC_MS_BTN1` |`KC_BTN1`|Mouse Button 1 | 29|`KC_MS_BTN1` |`KC_BTN1`|Mouse Button 1 |
31|`KC_MS_BTN2` |`KC_BTN2`|Mouse Button 2 | 30|`KC_MS_BTN2` |`KC_BTN2`|Mouse Button 2 |
32|`KC_MS_BTN3` |`KC_BTN3`|Mouse Button 3 | 31|`KC_MS_BTN3` |`KC_BTN3`|Mouse Button 3 |
33|`KC_MS_BTN4` |`KC_BTN4`|Mouse Button 4 | 32|`KC_MS_BTN4` |`KC_BTN4`|Mouse Button 4 |
34|`KC_MS_BTN5` |`KC_BTN5`|Mouse Button 5 | 33|`KC_MS_BTN5` |`KC_BTN5`|Mouse Button 5 |
35|`KC_MS_WH_UP` |`KC_WH_U`|Mouse Wheel Up | 34|`KC_MS_WH_UP` |`KC_WH_U`|Mouse Wheel Up |
36|`KC_MS_WH_DOWN` |`KC_WH_D`|Mouse Wheel Down | 35|`KC_MS_WH_DOWN` |`KC_WH_D`|Mouse Wheel Down |
37|`KC_MS_WH_LEFT` |`KC_WH_L`|Mouse Wheel Left | 36|`KC_MS_WH_LEFT` |`KC_WH_L`|Mouse Wheel Left |
38|`KC_MS_WH_RIGHT`|`KC_WH_R`|Mouse Wheel Right | 37|`KC_MS_WH_RIGHT`|`KC_WH_R`|Mouse Wheel Right |
39|`KC_MS_ACCEL0` |`KC_ACL0`|Set mouse acceleration to 0| 38|`KC_MS_ACCEL0` |`KC_ACL0`|Set mouse acceleration to 0(slow) |
40|`KC_MS_ACCEL1` |`KC_ACL1`|Set mouse acceleration to 1| 39|`KC_MS_ACCEL1` |`KC_ACL1`|Set mouse acceleration to 1(medium)|
41|`KC_MS_ACCEL2` |`KC_ACL2`|Set mouse acceleration to 2| 40|`KC_MS_ACCEL2` |`KC_ACL2`|Set mouse acceleration to 2(fast) |
42 41
43You can see an example in the `_ML` here: https://github.com/qmk/qmk_firmware/blob/master/keyboards/clueboard/66/keymaps/mouse_keys/keymap.c#L46 42
44 43## Configuring the Behavior of Mousekeys with auto-accelerated movement
45## Configuring the Behavior of Mousekeys 44
45This behavior is intended to emulate the X Window System MouseKeysAccel feature. You can read more about it [on Wikipedia](https://en.wikipedia.org/wiki/Mouse_keys).
46 46
47The default speed for controlling the mouse with the keyboard is intentionally slow. You can adjust these parameters by adding these settings to your keymap's `config.h` file. All times are specified in milliseconds (ms). 47The default speed for controlling the mouse with the keyboard is intentionally slow. You can adjust these parameters by adding these settings to your keymap's `config.h` file. All times are specified in milliseconds (ms).
48 48
@@ -55,27 +55,60 @@ The default speed for controlling the mouse with the keyboard is intentionally s
55#define MOUSEKEY_WHEEL_TIME_TO_MAX 40 55#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
56``` 56```
57 57
58 58#### `MOUSEKEY_DELAY`
59### `MOUSEKEY_DELAY`
60 59
61When one of the mouse movement buttons is pressed this setting is used to define the delay between that button press and the mouse cursor moving. Some people find that small movements are impossible if this setting is too low, while settings that are too high feel sluggish. 60When one of the mouse movement buttons is pressed this setting is used to define the delay between that button press and the mouse cursor moving. Some people find that small movements are impossible if this setting is too low, while settings that are too high feel sluggish.
62 61
63### `MOUSEKEY_INTERVAL` 62#### `MOUSEKEY_INTERVAL`
64 63
65When a movement key is held down this specifies how long to wait between each movement report. Lower settings will translate into an effectively higher mouse speed. 64When a movement key is held down this specifies how long to wait between each movement report. Lower settings will translate into an effectively higher mouse speed.
66 65
67### `MOUSEKEY_MAX_SPEED` 66#### `MOUSEKEY_MAX_SPEED`
68 67
69As a movement key is held down the speed of the mouse cursor will increase until it reaches `MOUSEKEY_MAX_SPEED`. 68As a movement key is held down the speed of the mouse cursor will increase until it reaches `MOUSEKEY_MAX_SPEED`.
70 69
71### `MOUSEKEY_TIME_TO_MAX` 70#### `MOUSEKEY_TIME_TO_MAX`
72 71
73How long you want to hold down a movement key for until `MOUSEKEY_MAX_SPEED` is reached. This controls how quickly your cursor will accelerate. 72How long you want to hold down a movement key for until `MOUSEKEY_MAX_SPEED` is reached. This controls how quickly your cursor will accelerate.
74 73
75### `MOUSEKEY_WHEEL_MAX_SPEED` 74#### `MOUSEKEY_WHEEL_MAX_SPEED`
76 75
77The top speed for scrolling movements. 76The top speed for scrolling movements.
78 77
79### `MOUSEKEY_WHEEL_TIME_TO_MAX` 78#### `MOUSEKEY_WHEEL_TIME_TO_MAX`
80 79
81How long you want to hold down a scroll key for until `MOUSEKEY_WHEEL_MAX_SPEED` is reached. This controls how quickly your scrolling will accelerate. 80How long you want to hold down a scroll key for until `MOUSEKEY_WHEEL_MAX_SPEED` is reached. This controls how quickly your scrolling will accelerate.
81
82
83## Configuring the Behavior of Mousekeys with 3-speed constant movement
84
85In your keymap's `config.h`, you must add the line:
86```
87#define MK_3_SPEED
88```
89Then you can precisely define 3 different speeds for both the cursor and the mouse wheel, and also whether speed selection is momentary or tap-to-select.
90For each speed, you can specify how many milliseconds you want between reports(interval), and how far you want to it to move per report(offset).
91
92For example:
93
94```
95#define MK_3_SPEED
96#define MK_MOMENTARY_ACCEL // comment this out for tap-to-select acceleration
97// cursor speeds:
98#define MK_C_OFFSET_SLOW 1 // pixels
99#define MK_C_INTERVAL_SLOW 100 // milliseconds
100#define MK_C_OFFSET_MED 4
101#define MK_C_INTERVAL_MED 16
102#define MK_C_OFFSET_FAST 12
103#define MK_C_INTERVAL_FAST 16
104// scroll wheel speeds:
105#define MK_W_OFFSET_SLOW 1 // wheel clicks
106#define MK_W_INTERVAL_SLOW 400 // milliseconds
107#define MK_W_OFFSET_MED 1
108#define MK_W_INTERVAL_MED 200
109#define MK_W_OFFSET_FAST 1
110#define MK_W_INTERVAL_FAST 100
111```
112
113Medium values will be used as the default or unmodified speed.
114The speed at which both the cursor and scrolling move can be selected with KC_ACL0, KC_ACL1, KC_ACL2 for slow, medium, and fast. However, if you leave MK_MOMENTARY_ACCEL defined then there is no need to ever send KC_ACL1, since that will be the unmodified speed.
diff --git a/tmk_core/common/mousekey.c b/tmk_core/common/mousekey.c
index 581e7b8a0..87239fbb7 100644
--- a/tmk_core/common/mousekey.c
+++ b/tmk_core/common/mousekey.c
@@ -23,13 +23,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
23#include "debug.h" 23#include "debug.h"
24#include "mousekey.h" 24#include "mousekey.h"
25 25
26inline int8_t times_inv_sqrt2(int8_t x) {
27 // 181/256 is pretty close to 1/sqrt(2)
28 // 0.70703125 0.707106781
29 // 1 too small for x=99 and x=198
30 // This ends up being a mult and discard lower 8 bits
31 return (x * 181) >> 8;
32}
26 33
27 34static report_mouse_t mouse_report = {0};
28static report_mouse_t mouse_report = {}; 35static void mousekey_debug(void);
29static uint8_t mousekey_repeat = 0;
30static uint8_t mousekey_accel = 0; 36static uint8_t mousekey_accel = 0;
37static uint8_t mousekey_repeat = 0;
38static uint16_t last_timer = 0;
39
40
41
42#ifndef MK_3_SPEED
31 43
32static void mousekey_debug(void);
33 44
34 45
35/* 46/*
@@ -52,155 +63,256 @@ uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
52uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED; 63uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
53uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX; 64uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
54 65
66static uint8_t move_unit(void) {
67 uint16_t unit;
68 if (mousekey_accel & (1<<0)) {
69 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/4;
70 } else if (mousekey_accel & (1<<1)) {
71 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/2;
72 } else if (mousekey_accel & (1<<2)) {
73 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
74 } else if (mousekey_repeat == 0) {
75 unit = MOUSEKEY_MOVE_DELTA;
76 } else if (mousekey_repeat >= mk_time_to_max) {
77 unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
78 } else {
79 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
80 }
81 return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
82}
55 83
56static uint16_t last_timer = 0; 84static uint8_t wheel_unit(void) {
85 uint16_t unit;
86 if (mousekey_accel & (1<<0)) {
87 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/4;
88 } else if (mousekey_accel & (1<<1)) {
89 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/2;
90 } else if (mousekey_accel & (1<<2)) {
91 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
92 } else if (mousekey_repeat == 0) {
93 unit = MOUSEKEY_WHEEL_DELTA;
94 } else if (mousekey_repeat >= mk_wheel_time_to_max) {
95 unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
96 } else {
97 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
98 }
99 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
100}
57 101
58inline int8_t times_inv_sqrt2(int8_t x) 102void mousekey_task(void) {
59{ 103 if (timer_elapsed(last_timer) < (mousekey_repeat ? mk_interval : mk_delay*10)) {
60 // 181/256 is pretty close to 1/sqrt(2) 104 return;
61 // 0.70703125 0.707106781 105 }
62 // 1 too small for x=99 and x=198 106 if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0) {
63 // This ends up being a mult and discard lower 8 bits 107 return;
64 return (x * 181) >> 8; 108 }
109 if (mousekey_repeat != UINT8_MAX) mousekey_repeat++;
110 if (mouse_report.x > 0) mouse_report.x = move_unit();
111 if (mouse_report.x < 0) mouse_report.x = move_unit() * -1;
112 if (mouse_report.y > 0) mouse_report.y = move_unit();
113 if (mouse_report.y < 0) mouse_report.y = move_unit() * -1;
114 /* diagonal move [1/sqrt(2)] */
115 if (mouse_report.x && mouse_report.y) {
116 mouse_report.x = times_inv_sqrt2(mouse_report.x);
117 mouse_report.y = times_inv_sqrt2(mouse_report.y);
118 }
119 if (mouse_report.v > 0) mouse_report.v = wheel_unit();
120 if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1;
121 if (mouse_report.h > 0) mouse_report.h = wheel_unit();
122 if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1;
123 mousekey_send();
65} 124}
66 125
67static uint8_t move_unit(void) 126void mousekey_on(uint8_t code) {
68{ 127 if (code == KC_MS_UP) mouse_report.y = move_unit() * -1;
69 uint16_t unit; 128 else if (code == KC_MS_DOWN) mouse_report.y = move_unit();
70 if (mousekey_accel & (1<<0)) { 129 else if (code == KC_MS_LEFT) mouse_report.x = move_unit() * -1;
71 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/4; 130 else if (code == KC_MS_RIGHT) mouse_report.x = move_unit();
72 } else if (mousekey_accel & (1<<1)) { 131 else if (code == KC_MS_WH_UP) mouse_report.v = wheel_unit();
73 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/2; 132 else if (code == KC_MS_WH_DOWN) mouse_report.v = wheel_unit() * -1;
74 } else if (mousekey_accel & (1<<2)) { 133 else if (code == KC_MS_WH_LEFT) mouse_report.h = wheel_unit() * -1;
75 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed); 134 else if (code == KC_MS_WH_RIGHT) mouse_report.h = wheel_unit();
76 } else if (mousekey_repeat == 0) { 135 else if (code == KC_MS_BTN1) mouse_report.buttons |= MOUSE_BTN1;
77 unit = MOUSEKEY_MOVE_DELTA; 136 else if (code == KC_MS_BTN2) mouse_report.buttons |= MOUSE_BTN2;
78 } else if (mousekey_repeat >= mk_time_to_max) { 137 else if (code == KC_MS_BTN3) mouse_report.buttons |= MOUSE_BTN3;
79 unit = MOUSEKEY_MOVE_DELTA * mk_max_speed; 138 else if (code == KC_MS_BTN4) mouse_report.buttons |= MOUSE_BTN4;
80 } else { 139 else if (code == KC_MS_BTN5) mouse_report.buttons |= MOUSE_BTN5;
81 unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max; 140 else if (code == KC_MS_ACCEL0) mousekey_accel |= (1<<0);
82 } 141 else if (code == KC_MS_ACCEL1) mousekey_accel |= (1<<1);
83 return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); 142 else if (code == KC_MS_ACCEL2) mousekey_accel |= (1<<2);
84} 143}
85 144
86static uint8_t wheel_unit(void) 145void mousekey_off(uint8_t code) {
87{ 146 if (code == KC_MS_UP && mouse_report.y < 0) mouse_report.y = 0;
88 uint16_t unit; 147 else if (code == KC_MS_DOWN && mouse_report.y > 0) mouse_report.y = 0;
89 if (mousekey_accel & (1<<0)) { 148 else if (code == KC_MS_LEFT && mouse_report.x < 0) mouse_report.x = 0;
90 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/4; 149 else if (code == KC_MS_RIGHT && mouse_report.x > 0) mouse_report.x = 0;
91 } else if (mousekey_accel & (1<<1)) { 150 else if (code == KC_MS_WH_UP && mouse_report.v > 0) mouse_report.v = 0;
92 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/2; 151 else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) mouse_report.v = 0;
93 } else if (mousekey_accel & (1<<2)) { 152 else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) mouse_report.h = 0;
94 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed); 153 else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0;
95 } else if (mousekey_repeat == 0) { 154 else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1;
96 unit = MOUSEKEY_WHEEL_DELTA; 155 else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2;
97 } else if (mousekey_repeat >= mk_wheel_time_to_max) { 156 else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3;
98 unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed; 157 else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4;
99 } else { 158 else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5;
100 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max; 159 else if (code == KC_MS_ACCEL0) mousekey_accel &= ~(1<<0);
101 } 160 else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1<<1);
102 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); 161 else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1<<2);
162 if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
163 mousekey_repeat = 0;
103} 164}
104 165
105void mousekey_task(void)
106{
107 if (timer_elapsed(last_timer) < (mousekey_repeat ? mk_interval : mk_delay*10))
108 return;
109 166
110 if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
111 return;
112 167
113 if (mousekey_repeat != UINT8_MAX) 168
114 mousekey_repeat++; 169#else /* #ifndef MK_3_SPEED */
115 170
116 171
117 if (mouse_report.x > 0) mouse_report.x = move_unit();
118 if (mouse_report.x < 0) mouse_report.x = move_unit() * -1;
119 if (mouse_report.y > 0) mouse_report.y = move_unit();
120 if (mouse_report.y < 0) mouse_report.y = move_unit() * -1;
121 172
122 /* diagonal move [1/sqrt(2)] */ 173enum {
123 if (mouse_report.x && mouse_report.y) { 174 mkspd_slow,
124 mouse_report.x = times_inv_sqrt2(mouse_report.x); 175 mkspd_med,
125 mouse_report.x = mouse_report.x == 0 ? 1 : mouse_report.x; 176 mkspd_fast,
126 mouse_report.y = times_inv_sqrt2(mouse_report.y); 177 mkspd_COUNT
127 mouse_report.y = mouse_report.y == 0 ? 1 : mouse_report.y; 178};
128 } 179static uint8_t mk_speed = mkspd_med;
180#ifdef MK_MOMENTARY_ACCEL
181static uint8_t mkspd_DEFAULT = mkspd_med;
182#endif
183static uint16_t last_timer_c = 0;
184static uint16_t last_timer_w = 0;
185uint16_t c_offsets[mkspd_COUNT] = {
186 MK_C_OFFSET_SLOW, MK_C_OFFSET_MED, MK_C_OFFSET_FAST
187};
188uint16_t c_intervals[mkspd_COUNT] = {
189 MK_C_INTERVAL_SLOW, MK_C_INTERVAL_MED, MK_C_INTERVAL_FAST
190};
191uint16_t w_offsets[mkspd_COUNT] = {
192 MK_W_OFFSET_SLOW, MK_W_OFFSET_MED, MK_W_OFFSET_FAST
193};
194uint16_t w_intervals[mkspd_COUNT] = {
195 MK_W_INTERVAL_SLOW, MK_W_INTERVAL_MED, MK_W_INTERVAL_FAST
196};
129 197
130 if (mouse_report.v > 0) mouse_report.v = wheel_unit();
131 if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1;
132 if (mouse_report.h > 0) mouse_report.h = wheel_unit();
133 if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1;
134 198
135 mousekey_send(); 199void mousekey_task(void) {
200 // report cursor and scroll movement independently
201 report_mouse_t const tmpmr = mouse_report;
202 if ((mouse_report.x || mouse_report.y) && timer_elapsed(last_timer_c) > c_intervals[mk_speed]) {
203 mouse_report.h = 0;
204 mouse_report.v = 0;
205 mousekey_send();
206 last_timer_c = last_timer;
207 mouse_report = tmpmr;
208 }
209 if ((mouse_report.h || mouse_report.v) && timer_elapsed(last_timer_w) > w_intervals[mk_speed]) {
210 mouse_report.x = 0;
211 mouse_report.y = 0;
212 mousekey_send();
213 last_timer_w = last_timer;
214 mouse_report = tmpmr;
215 }
136} 216}
137 217
138void mousekey_on(uint8_t code) 218void adjust_speed(void) {
139{ 219 uint16_t const c_offset = c_offsets[mk_speed];
140 if (code == KC_MS_UP) mouse_report.y = move_unit() * -1; 220 uint16_t const w_offset = w_offsets[mk_speed];
141 else if (code == KC_MS_DOWN) mouse_report.y = move_unit(); 221 if (mouse_report.x > 0) mouse_report.x = c_offset;
142 else if (code == KC_MS_LEFT) mouse_report.x = move_unit() * -1; 222 if (mouse_report.x < 0) mouse_report.x = c_offset * -1;
143 else if (code == KC_MS_RIGHT) mouse_report.x = move_unit(); 223 if (mouse_report.y > 0) mouse_report.y = c_offset;
144 else if (code == KC_MS_WH_UP) mouse_report.v = wheel_unit(); 224 if (mouse_report.y < 0) mouse_report.y = c_offset * -1;
145 else if (code == KC_MS_WH_DOWN) mouse_report.v = wheel_unit() * -1; 225 if (mouse_report.h > 0) mouse_report.h = w_offset;
146 else if (code == KC_MS_WH_LEFT) mouse_report.h = wheel_unit() * -1; 226 if (mouse_report.h < 0) mouse_report.h = w_offset * -1;
147 else if (code == KC_MS_WH_RIGHT) mouse_report.h = wheel_unit(); 227 if (mouse_report.v > 0) mouse_report.v = w_offset;
148 else if (code == KC_MS_BTN1) mouse_report.buttons |= MOUSE_BTN1; 228 if (mouse_report.v < 0) mouse_report.v = w_offset * -1;
149 else if (code == KC_MS_BTN2) mouse_report.buttons |= MOUSE_BTN2; 229 // adjust for diagonals
150 else if (code == KC_MS_BTN3) mouse_report.buttons |= MOUSE_BTN3; 230 if (mouse_report.x && mouse_report.y) {
151 else if (code == KC_MS_BTN4) mouse_report.buttons |= MOUSE_BTN4; 231 mouse_report.x = times_inv_sqrt2(mouse_report.x);
152 else if (code == KC_MS_BTN5) mouse_report.buttons |= MOUSE_BTN5; 232 mouse_report.y = times_inv_sqrt2(mouse_report.y);
153 else if (code == KC_MS_ACCEL0) mousekey_accel |= (1<<0); 233 }
154 else if (code == KC_MS_ACCEL1) mousekey_accel |= (1<<1); 234 if (mouse_report.h && mouse_report.v) {
155 else if (code == KC_MS_ACCEL2) mousekey_accel |= (1<<2); 235 mouse_report.h = times_inv_sqrt2(mouse_report.h);
236 mouse_report.v = times_inv_sqrt2(mouse_report.v);
237 }
156} 238}
157 239
158void mousekey_off(uint8_t code) 240void mousekey_on(uint8_t code) {
159{ 241 uint16_t const c_offset = c_offsets[mk_speed];
160 if (code == KC_MS_UP && mouse_report.y < 0) mouse_report.y = 0; 242 uint16_t const w_offset = w_offsets[mk_speed];
161 else if (code == KC_MS_DOWN && mouse_report.y > 0) mouse_report.y = 0; 243 uint8_t const old_speed = mk_speed;
162 else if (code == KC_MS_LEFT && mouse_report.x < 0) mouse_report.x = 0; 244 if (code == KC_MS_UP) mouse_report.y = c_offset * -1;
163 else if (code == KC_MS_RIGHT && mouse_report.x > 0) mouse_report.x = 0; 245 else if (code == KC_MS_DOWN) mouse_report.y = c_offset;
164 else if (code == KC_MS_WH_UP && mouse_report.v > 0) mouse_report.v = 0; 246 else if (code == KC_MS_LEFT) mouse_report.x = c_offset * -1;
165 else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) mouse_report.v = 0; 247 else if (code == KC_MS_RIGHT) mouse_report.x = c_offset;
166 else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) mouse_report.h = 0; 248 else if (code == KC_MS_WH_UP) mouse_report.v = w_offset;
167 else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0; 249 else if (code == KC_MS_WH_DOWN) mouse_report.v = w_offset * -1;
168 else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1; 250 else if (code == KC_MS_WH_LEFT) mouse_report.h = w_offset * -1;
169 else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2; 251 else if (code == KC_MS_WH_RIGHT) mouse_report.h = w_offset;
170 else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3; 252 else if (code == KC_MS_BTN1) mouse_report.buttons |= MOUSE_BTN1;
171 else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4; 253 else if (code == KC_MS_BTN2) mouse_report.buttons |= MOUSE_BTN2;
172 else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5; 254 else if (code == KC_MS_BTN3) mouse_report.buttons |= MOUSE_BTN3;
173 else if (code == KC_MS_ACCEL0) mousekey_accel &= ~(1<<0); 255 else if (code == KC_MS_BTN4) mouse_report.buttons |= MOUSE_BTN4;
174 else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1<<1); 256 else if (code == KC_MS_BTN5) mouse_report.buttons |= MOUSE_BTN5;
175 else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1<<2); 257 else if (code == KC_MS_ACCEL0) mk_speed = mkspd_slow;
176 258 else if (code == KC_MS_ACCEL1) mk_speed = mkspd_med;
177 if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0) 259 else if (code == KC_MS_ACCEL2) mk_speed = mkspd_fast;
178 mousekey_repeat = 0; 260 if (mk_speed != old_speed) adjust_speed();
179} 261}
180 262
181void mousekey_send(void) 263void mousekey_off(uint8_t code) {
182{ 264#ifdef MK_MOMENTARY_ACCEL
183 mousekey_debug(); 265 uint8_t const old_speed = mk_speed;
184 host_mouse_send(&mouse_report); 266#endif
185 last_timer = timer_read(); 267 if (code == KC_MS_UP && mouse_report.y < 0) mouse_report.y = 0;
268 else if (code == KC_MS_DOWN && mouse_report.y > 0) mouse_report.y = 0;
269 else if (code == KC_MS_LEFT && mouse_report.x < 0) mouse_report.x = 0;
270 else if (code == KC_MS_RIGHT && mouse_report.x > 0) mouse_report.x = 0;
271 else if (code == KC_MS_WH_UP && mouse_report.v > 0) mouse_report.v = 0;
272 else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) mouse_report.v = 0;
273 else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) mouse_report.h = 0;
274 else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0;
275 else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1;
276 else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2;
277 else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3;
278 else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4;
279 else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5;
280#ifdef MK_MOMENTARY_ACCEL
281 else if (code == KC_MS_ACCEL0) mk_speed = mkspd_DEFAULT;
282 else if (code == KC_MS_ACCEL1) mk_speed = mkspd_DEFAULT;
283 else if (code == KC_MS_ACCEL2) mk_speed = mkspd_DEFAULT;
284 if (mk_speed != old_speed) adjust_speed();
285#endif
186} 286}
187 287
188void mousekey_clear(void) 288
189{ 289
190 mouse_report = (report_mouse_t){}; 290
191 mousekey_repeat = 0; 291#endif /* #ifndef MK_3_SPEED */
192 mousekey_accel = 0; 292
293
294
295
296void mousekey_send(void) {
297 mousekey_debug();
298 host_mouse_send(&mouse_report);
299 last_timer = timer_read();
300}
301
302void mousekey_clear(void) {
303 mouse_report = (report_mouse_t){};
304 mousekey_repeat = 0;
305 mousekey_accel = 0;
193} 306}
194 307
195static void mousekey_debug(void) 308static void mousekey_debug(void) {
196{ 309 if (!debug_mouse) return;
197 if (!debug_mouse) return; 310 print("mousekey [btn|x y v h](rep/acl): [");
198 print("mousekey [btn|x y v h](rep/acl): ["); 311 phex(mouse_report.buttons); print("|");
199 phex(mouse_report.buttons); print("|"); 312 print_decs(mouse_report.x); print(" ");
200 print_decs(mouse_report.x); print(" "); 313 print_decs(mouse_report.y); print(" ");
201 print_decs(mouse_report.y); print(" "); 314 print_decs(mouse_report.v); print(" ");
202 print_decs(mouse_report.v); print(" "); 315 print_decs(mouse_report.h); print("](");
203 print_decs(mouse_report.h); print("]("); 316 print_dec(mousekey_repeat); print("/");
204 print_dec(mousekey_repeat); print("/"); 317 print_dec(mousekey_accel); print(")\n");
205 print_dec(mousekey_accel); print(")\n");
206} 318}
diff --git a/tmk_core/common/mousekey.h b/tmk_core/common/mousekey.h
index 9338d0af7..ce3501b23 100644
--- a/tmk_core/common/mousekey.h
+++ b/tmk_core/common/mousekey.h
@@ -16,23 +16,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17 17
18#ifndef MOUSEKEY_H 18#ifndef MOUSEKEY_H
19#define MOUSEKEY_H 19#define MOUSEKEY_H
20#endif
20 21
21#include <stdbool.h> 22#include <stdbool.h>
22#include "host.h" 23#include "host.h"
23 24
25#ifndef MK_3_SPEED
24 26
25/* max value on report descriptor */ 27/* max value on report descriptor */
26#ifndef MOUSEKEY_MOVE_MAX 28#ifndef MOUSEKEY_MOVE_MAX
27 #define MOUSEKEY_MOVE_MAX 127 29 #define MOUSEKEY_MOVE_MAX 127
28#elif MOUSEKEY_MOVE_MAX > 127 30#elif MOUSEKEY_MOVE_MAX > 127
29 #error MOUSEKEY_MOVE_MAX needs to be smaller than 127 31 #error MOUSEKEY_MOVE_MAX needs to be smaller than 127
30#endif 32#endif
31 33
32#ifndef MOUSEKEY_WHEEL_MAX 34#ifndef MOUSEKEY_WHEEL_MAX
33 #define MOUSEKEY_WHEEL_MAX 127 35 #define MOUSEKEY_WHEEL_MAX 127
34#elif MOUSEKEY_WHEEL_MAX > 127 36#elif MOUSEKEY_WHEEL_MAX > 127
35 #error MOUSEKEY_WHEEL_MAX needs to be smaller than 127 37 #error MOUSEKEY_WHEEL_MAX needs to be smaller than 127
36#endif 38#endif
37 39
38#ifndef MOUSEKEY_MOVE_DELTA 40#ifndef MOUSEKEY_MOVE_DELTA
@@ -60,6 +62,47 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
60#define MOUSEKEY_WHEEL_TIME_TO_MAX 40 62#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
61#endif 63#endif
62 64
65#else /* #ifndef MK_3_SPEED */
66
67#ifndef MK_C_OFFSET_SLOW
68#define MK_C_OFFSET_SLOW 1
69#endif
70#ifndef MK_C_INTERVAL_SLOW
71#define MK_C_INTERVAL_SLOW 100
72#endif
73#ifndef MK_C_OFFSET_MED
74#define MK_C_OFFSET_MED 4
75#endif
76#ifndef MK_C_INTERVAL_MED
77#define MK_C_INTERVAL_MED 16
78#endif
79#ifndef MK_C_OFFSET_FAST
80#define MK_C_OFFSET_FAST 12
81#endif
82#ifndef MK_C_INTERVAL_FAST
83#define MK_C_INTERVAL_FAST 16
84#endif
85
86#ifndef MK_W_OFFSET_SLOW
87#define MK_W_OFFSET_SLOW 1
88#endif
89#ifndef MK_W_INTERVAL_SLOW
90#define MK_W_INTERVAL_SLOW 400
91#endif
92#ifndef MK_W_OFFSET_MED
93#define MK_W_OFFSET_MED 1
94#endif
95#ifndef MK_W_INTERVAL_MED
96#define MK_W_INTERVAL_MED 200
97#endif
98#ifndef MK_W_OFFSET_FAST
99#define MK_W_OFFSET_FAST 1
100#endif
101#ifndef MK_W_INTERVAL_FAST
102#define MK_W_INTERVAL_FAST 100
103#endif
104
105#endif /* #ifndef MK_3_SPEED */
63 106
64#ifdef __cplusplus 107#ifdef __cplusplus
65extern "C" { 108extern "C" {
@@ -72,7 +115,6 @@ extern uint8_t mk_time_to_max;
72extern uint8_t mk_wheel_max_speed; 115extern uint8_t mk_wheel_max_speed;
73extern uint8_t mk_wheel_time_to_max; 116extern uint8_t mk_wheel_time_to_max;
74 117
75
76void mousekey_task(void); 118void mousekey_task(void);
77void mousekey_on(uint8_t code); 119void mousekey_on(uint8_t code);
78void mousekey_off(uint8_t code); 120void mousekey_off(uint8_t code);
@@ -82,5 +124,3 @@ void mousekey_send(void);
82#ifdef __cplusplus 124#ifdef __cplusplus
83} 125}
84#endif 126#endif
85
86#endif