You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

653 lines
23 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. /*
  2. * Copyright 2011 Jun Wako <wakojun@gmail.com>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdint.h>
  18. #include <string.h>
  19. #include "keycode.h"
  20. #include "host.h"
  21. #include "timer.h"
  22. #include "print.h"
  23. #include "debug.h"
  24. #include "mousekey.h"
  25. inline int8_t times_inv_sqrt2(int8_t x) {
  26. // 181/256 is pretty close to 1/sqrt(2)
  27. // 0.70703125 0.707106781
  28. // 1 too small for x=99 and x=198
  29. // This ends up being a mult and discard lower 8 bits
  30. return (x * 181) >> 8;
  31. }
  32. static report_mouse_t mouse_report = {0};
  33. static void mousekey_debug(void);
  34. static uint8_t mousekey_accel = 0;
  35. static uint8_t mousekey_repeat = 0;
  36. static uint8_t mousekey_wheel_repeat = 0;
  37. #ifdef MOUSEKEY_INERTIA
  38. static uint8_t mousekey_frame = 0; // track whether gesture is inactive, first frame, or repeating
  39. static int8_t mousekey_x_dir = 0; // -1 / 0 / 1 = left / neutral / right
  40. static int8_t mousekey_y_dir = 0; // -1 / 0 / 0 = up / neutral / down
  41. static int8_t mousekey_x_inertia = 0; // current velocity, limit +/- MOUSEKEY_TIME_TO_MAX
  42. static int8_t mousekey_y_inertia = 0; // ...
  43. #endif
  44. #ifdef MK_KINETIC_SPEED
  45. static uint16_t mouse_timer = 0;
  46. #endif
  47. #ifndef MK_3_SPEED
  48. static uint16_t last_timer_c = 0;
  49. static uint16_t last_timer_w = 0;
  50. /*
  51. * Mouse keys acceleration algorithm
  52. * http://en.wikipedia.org/wiki/Mouse_keys
  53. *
  54. * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
  55. */
  56. /* milliseconds between the initial key press and first repeated motion event (0-2550) */
  57. uint8_t mk_delay = MOUSEKEY_DELAY / 10;
  58. /* milliseconds between repeated motion events (0-255) */
  59. uint8_t mk_interval = MOUSEKEY_INTERVAL;
  60. /* steady speed (in action_delta units) applied each event (0-255) */
  61. uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
  62. /* number of events (count) accelerating to steady speed (0-255) */
  63. uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
  64. /* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
  65. // int8_t mk_curve = 0;
  66. /* wheel params */
  67. /* milliseconds between the initial key press and first repeated motion event (0-2550) */
  68. uint8_t mk_wheel_delay = MOUSEKEY_WHEEL_DELAY / 10;
  69. /* milliseconds between repeated motion events (0-255) */
  70. # ifdef MK_KINETIC_SPEED
  71. float mk_wheel_interval = 1000.0f / MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
  72. # else
  73. uint8_t mk_wheel_interval = MOUSEKEY_WHEEL_INTERVAL;
  74. # endif
  75. uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
  76. uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
  77. # ifndef MK_COMBINED
  78. # ifndef MK_KINETIC_SPEED
  79. # ifndef MOUSEKEY_INERTIA
  80. /* Default accelerated mode */
  81. static uint8_t move_unit(void) {
  82. uint16_t unit;
  83. if (mousekey_accel & (1 << 0)) {
  84. unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4;
  85. } else if (mousekey_accel & (1 << 1)) {
  86. unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2;
  87. } else if (mousekey_accel & (1 << 2)) {
  88. unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
  89. } else if (mousekey_repeat == 0) {
  90. unit = MOUSEKEY_MOVE_DELTA;
  91. } else if (mousekey_repeat >= mk_time_to_max) {
  92. unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
  93. } else {
  94. unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
  95. }
  96. return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
  97. }
  98. # else // MOUSEKEY_INERTIA mode
  99. static int8_t move_unit(uint8_t axis) {
  100. int16_t unit;
  101. // handle X or Y axis
  102. int8_t inertia, dir;
  103. if (axis) {
  104. inertia = mousekey_y_inertia;
  105. dir = mousekey_y_dir;
  106. } else {
  107. inertia = mousekey_x_inertia;
  108. dir = mousekey_x_dir;
  109. }
  110. if (mousekey_frame < 2) { // first frame(s): initial keypress moves one pixel
  111. mousekey_frame = 1;
  112. unit = dir * MOUSEKEY_MOVE_DELTA;
  113. } else { // acceleration
  114. // linear acceleration (is here for reference, but doesn't feel as good during use)
  115. // unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * inertia) / mk_time_to_max;
  116. // x**2 acceleration (quadratic, more precise for short movements)
  117. int16_t percent = (inertia << 8) / mk_time_to_max;
  118. percent = ((int32_t)percent * percent) >> 8;
  119. if (inertia < 0) percent = -percent;
  120. // unit = sign(inertia) + (percent of max speed)
  121. if (inertia > 0)
  122. unit = 1;
  123. else if (inertia < 0)
  124. unit = -1;
  125. else
  126. unit = 0;
  127. unit = unit + ((mk_max_speed * percent) >> 8);
  128. }
  129. if (unit > MOUSEKEY_MOVE_MAX)
  130. unit = MOUSEKEY_MOVE_MAX;
  131. else if (unit < -MOUSEKEY_MOVE_MAX)
  132. unit = -MOUSEKEY_MOVE_MAX;
  133. return unit;
  134. }
  135. # endif // end MOUSEKEY_INERTIA mode
  136. static uint8_t wheel_unit(void) {
  137. uint16_t unit;
  138. if (mousekey_accel & (1 << 0)) {
  139. unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4;
  140. } else if (mousekey_accel & (1 << 1)) {
  141. unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2;
  142. } else if (mousekey_accel & (1 << 2)) {
  143. unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
  144. } else if (mousekey_wheel_repeat == 0) {
  145. unit = MOUSEKEY_WHEEL_DELTA;
  146. } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) {
  147. unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
  148. } else {
  149. unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_wheel_repeat) / mk_wheel_time_to_max;
  150. }
  151. return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
  152. }
  153. # else /* #ifndef MK_KINETIC_SPEED */
  154. /*
  155. * Kinetic movement acceleration algorithm
  156. *
  157. * current speed = I + A * T/50 + A * 0.5 * T^2 | maximum B
  158. *
  159. * T: time since the mouse movement started
  160. * E: mouse events per second (set through MOUSEKEY_INTERVAL, UHK sends 250, the
  161. * pro micro on my Signum 3.0 sends only 125!)
  162. * I: initial speed at time 0
  163. * A: acceleration
  164. * B: base mouse travel speed
  165. */
  166. const uint16_t mk_accelerated_speed = MOUSEKEY_ACCELERATED_SPEED;
  167. const uint16_t mk_base_speed = MOUSEKEY_BASE_SPEED;
  168. const uint16_t mk_decelerated_speed = MOUSEKEY_DECELERATED_SPEED;
  169. const uint16_t mk_initial_speed = MOUSEKEY_INITIAL_SPEED;
  170. static uint8_t move_unit(void) {
  171. float speed = mk_initial_speed;
  172. if (mousekey_accel & ((1 << 0) | (1 << 2))) {
  173. speed = mousekey_accel & (1 << 2) ? mk_accelerated_speed : mk_decelerated_speed;
  174. } else if (mousekey_repeat && mouse_timer) {
  175. const float time_elapsed = timer_elapsed(mouse_timer) / 50;
  176. speed = mk_initial_speed + MOUSEKEY_MOVE_DELTA * time_elapsed + MOUSEKEY_MOVE_DELTA * 0.5 * time_elapsed * time_elapsed;
  177. speed = speed > mk_base_speed ? mk_base_speed : speed;
  178. }
  179. /* convert speed to USB mouse speed 1 to 127 */
  180. speed = (uint8_t)(speed / (1000.0f / mk_interval));
  181. speed = speed < 1 ? 1 : speed;
  182. return speed > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : speed;
  183. }
  184. static uint8_t wheel_unit(void) {
  185. float speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS;
  186. if (mousekey_accel & ((1 << 0) | (1 << 2))) {
  187. speed = mousekey_accel & (1 << 2) ? MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS : MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS;
  188. } else if (mousekey_wheel_repeat && mouse_timer) {
  189. if (mk_wheel_interval != MOUSEKEY_WHEEL_BASE_MOVEMENTS) {
  190. const float time_elapsed = timer_elapsed(mouse_timer) / 50;
  191. speed = MOUSEKEY_WHEEL_INITIAL_MOVEMENTS + 1 * time_elapsed + 1 * 0.5 * time_elapsed * time_elapsed;
  192. }
  193. speed = speed > MOUSEKEY_WHEEL_BASE_MOVEMENTS ? MOUSEKEY_WHEEL_BASE_MOVEMENTS : speed;
  194. }
  195. mk_wheel_interval = 1000.0f / speed;
  196. return (uint8_t)speed > MOUSEKEY_WHEEL_INITIAL_MOVEMENTS ? 2 : 1;
  197. }
  198. # endif /* #ifndef MK_KINETIC_SPEED */
  199. # else /* #ifndef MK_COMBINED */
  200. /* Combined mode */
  201. static uint8_t move_unit(void) {
  202. uint16_t unit;
  203. if (mousekey_accel & (1 << 0)) {
  204. unit = 1;
  205. } else if (mousekey_accel & (1 << 1)) {
  206. unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2;
  207. } else if (mousekey_accel & (1 << 2)) {
  208. unit = MOUSEKEY_MOVE_MAX;
  209. } else if (mousekey_repeat == 0) {
  210. unit = MOUSEKEY_MOVE_DELTA;
  211. } else if (mousekey_repeat >= mk_time_to_max) {
  212. unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
  213. } else {
  214. unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
  215. }
  216. return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
  217. }
  218. static uint8_t wheel_unit(void) {
  219. uint16_t unit;
  220. if (mousekey_accel & (1 << 0)) {
  221. unit = 1;
  222. } else if (mousekey_accel & (1 << 1)) {
  223. unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2;
  224. } else if (mousekey_accel & (1 << 2)) {
  225. unit = MOUSEKEY_WHEEL_MAX;
  226. } else if (mousekey_repeat == 0) {
  227. unit = MOUSEKEY_WHEEL_DELTA;
  228. } else if (mousekey_repeat >= mk_wheel_time_to_max) {
  229. unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
  230. } else {
  231. unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
  232. }
  233. return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
  234. }
  235. # endif /* #ifndef MK_COMBINED */
  236. # ifdef MOUSEKEY_INERTIA
  237. static int8_t calc_inertia(int8_t direction, int8_t velocity) {
  238. // simulate acceleration and deceleration
  239. // deceleration
  240. if ((direction > -1) && (velocity < 0))
  241. velocity = (velocity + 1) * (256 - MOUSEKEY_FRICTION) / 256;
  242. else if ((direction < 1) && (velocity > 0))
  243. velocity = velocity * (256 - MOUSEKEY_FRICTION) / 256;
  244. // acceleration
  245. if ((direction > 0) && (velocity < mk_time_to_max))
  246. velocity++;
  247. else if ((direction < 0) && (velocity > -mk_time_to_max))
  248. velocity--;
  249. return velocity;
  250. }
  251. # endif
  252. void mousekey_task(void) {
  253. // report cursor and scroll movement independently
  254. report_mouse_t tmpmr = mouse_report;
  255. mouse_report.x = 0;
  256. mouse_report.y = 0;
  257. mouse_report.v = 0;
  258. mouse_report.h = 0;
  259. # ifdef MOUSEKEY_INERTIA
  260. // if an animation is in progress and it's time for the next frame
  261. if ((mousekey_frame) && timer_elapsed(last_timer_c) > ((mousekey_frame > 1) ? mk_interval : mk_delay * 10)) {
  262. mousekey_x_inertia = calc_inertia(mousekey_x_dir, mousekey_x_inertia);
  263. mousekey_y_inertia = calc_inertia(mousekey_y_dir, mousekey_y_inertia);
  264. mouse_report.x = move_unit(0);
  265. mouse_report.y = move_unit(1);
  266. // prevent sticky "drift"
  267. if ((!mousekey_x_dir) && (!mousekey_x_inertia)) tmpmr.x = 0;
  268. if ((!mousekey_y_dir) && (!mousekey_y_inertia)) tmpmr.y = 0;
  269. if (mousekey_frame < 2) mousekey_frame++;
  270. }
  271. // reset if not moving and no movement keys are held
  272. if ((!mousekey_x_dir) && (!mousekey_y_dir) && (!mousekey_x_inertia) && (!mousekey_y_inertia)) {
  273. mousekey_frame = 0;
  274. tmpmr.x = 0;
  275. tmpmr.y = 0;
  276. }
  277. # else // default acceleration
  278. if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) {
  279. if (mousekey_repeat != UINT8_MAX) mousekey_repeat++;
  280. if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1);
  281. if (tmpmr.y != 0) mouse_report.y = move_unit() * ((tmpmr.y > 0) ? 1 : -1);
  282. /* diagonal move [1/sqrt(2)] */
  283. if (mouse_report.x && mouse_report.y) {
  284. mouse_report.x = times_inv_sqrt2(mouse_report.x);
  285. if (mouse_report.x == 0) {
  286. mouse_report.x = 1;
  287. }
  288. mouse_report.y = times_inv_sqrt2(mouse_report.y);
  289. if (mouse_report.y == 0) {
  290. mouse_report.y = 1;
  291. }
  292. }
  293. }
  294. # endif // MOUSEKEY_INERTIA or not
  295. if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) {
  296. if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++;
  297. if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1);
  298. if (tmpmr.h != 0) mouse_report.h = wheel_unit() * ((tmpmr.h > 0) ? 1 : -1);
  299. /* diagonal move [1/sqrt(2)] */
  300. if (mouse_report.v && mouse_report.h) {
  301. mouse_report.v = times_inv_sqrt2(mouse_report.v);
  302. if (mouse_report.v == 0) {
  303. mouse_report.v = 1;
  304. }
  305. mouse_report.h = times_inv_sqrt2(mouse_report.h);
  306. if (mouse_report.h == 0) {
  307. mouse_report.h = 1;
  308. }
  309. }
  310. }
  311. if (has_mouse_report_changed(&mouse_report, &tmpmr) || should_mousekey_report_send(&mouse_report)) {
  312. mousekey_send();
  313. }
  314. // save the state for later
  315. memcpy(&mouse_report, &tmpmr, sizeof(tmpmr));
  316. }
  317. void mousekey_on(uint8_t code) {
  318. # ifdef MK_KINETIC_SPEED
  319. if (mouse_timer == 0) {
  320. mouse_timer = timer_read();
  321. }
  322. # endif /* #ifdef MK_KINETIC_SPEED */
  323. # ifdef MOUSEKEY_INERTIA
  324. // initial keypress sets impulse and activates first frame of movement
  325. if ((code == KC_MS_UP) || (code == KC_MS_DOWN)) {
  326. mousekey_y_dir = (code == KC_MS_DOWN) ? 1 : -1;
  327. if (mousekey_frame < 2) mouse_report.y = move_unit(1);
  328. } else if ((code == KC_MS_LEFT) || (code == KC_MS_RIGHT)) {
  329. mousekey_x_dir = (code == KC_MS_RIGHT) ? 1 : -1;
  330. if (mousekey_frame < 2) mouse_report.x = move_unit(0);
  331. }
  332. # else // no inertia
  333. if (code == KC_MS_UP)
  334. mouse_report.y = move_unit() * -1;
  335. else if (code == KC_MS_DOWN)
  336. mouse_report.y = move_unit();
  337. else if (code == KC_MS_LEFT)
  338. mouse_report.x = move_unit() * -1;
  339. else if (code == KC_MS_RIGHT)
  340. mouse_report.x = move_unit();
  341. # endif // inertia or not
  342. else if (code == KC_MS_WH_UP)
  343. mouse_report.v = wheel_unit();
  344. else if (code == KC_MS_WH_DOWN)
  345. mouse_report.v = wheel_unit() * -1;
  346. else if (code == KC_MS_WH_LEFT)
  347. mouse_report.h = wheel_unit() * -1;
  348. else if (code == KC_MS_WH_RIGHT)
  349. mouse_report.h = wheel_unit();
  350. else if (IS_MOUSEKEY_BUTTON(code))
  351. mouse_report.buttons |= 1 << (code - KC_MS_BTN1);
  352. else if (code == KC_MS_ACCEL0)
  353. mousekey_accel |= (1 << 0);
  354. else if (code == KC_MS_ACCEL1)
  355. mousekey_accel |= (1 << 1);
  356. else if (code == KC_MS_ACCEL2)
  357. mousekey_accel |= (1 << 2);
  358. }
  359. void mousekey_off(uint8_t code) {
  360. # ifdef MOUSEKEY_INERTIA
  361. // key release clears impulse unless opposite direction is held
  362. if ((code == KC_MS_UP) && (mousekey_y_dir < 1))
  363. mousekey_y_dir = 0;
  364. else if ((code == KC_MS_DOWN) && (mousekey_y_dir > -1))
  365. mousekey_y_dir = 0;
  366. else if ((code == KC_MS_LEFT) && (mousekey_x_dir < 1))
  367. mousekey_x_dir = 0;
  368. else if ((code == KC_MS_RIGHT) && (mousekey_x_dir > -1))
  369. mousekey_x_dir = 0;
  370. # else // no inertia
  371. if (code == KC_MS_UP && mouse_report.y < 0)
  372. mouse_report.y = 0;
  373. else if (code == KC_MS_DOWN && mouse_report.y > 0)
  374. mouse_report.y = 0;
  375. else if (code == KC_MS_LEFT && mouse_report.x < 0)
  376. mouse_report.x = 0;
  377. else if (code == KC_MS_RIGHT && mouse_report.x > 0)
  378. mouse_report.x = 0;
  379. # endif // inertia or not
  380. else if (code == KC_MS_WH_UP && mouse_report.v > 0)
  381. mouse_report.v = 0;
  382. else if (code == KC_MS_WH_DOWN && mouse_report.v < 0)
  383. mouse_report.v = 0;
  384. else if (code == KC_MS_WH_LEFT && mouse_report.h < 0)
  385. mouse_report.h = 0;
  386. else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0)
  387. mouse_report.h = 0;
  388. else if (IS_MOUSEKEY_BUTTON(code))
  389. mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1));
  390. else if (code == KC_MS_ACCEL0)
  391. mousekey_accel &= ~(1 << 0);
  392. else if (code == KC_MS_ACCEL1)
  393. mousekey_accel &= ~(1 << 1);
  394. else if (code == KC_MS_ACCEL2)
  395. mousekey_accel &= ~(1 << 2);
  396. if (mouse_report.x == 0 && mouse_report.y == 0) {
  397. mousekey_repeat = 0;
  398. # ifdef MK_KINETIC_SPEED
  399. mouse_timer = 0;
  400. # endif /* #ifdef MK_KINETIC_SPEED */
  401. }
  402. if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0;
  403. }
  404. #else /* #ifndef MK_3_SPEED */
  405. enum { mkspd_unmod, mkspd_0, mkspd_1, mkspd_2, mkspd_COUNT };
  406. # ifndef MK_MOMENTARY_ACCEL
  407. static uint8_t mk_speed = mkspd_1;
  408. # else
  409. static uint8_t mk_speed = mkspd_unmod;
  410. static uint8_t mkspd_DEFAULT = mkspd_unmod;
  411. # endif
  412. static uint16_t last_timer_c = 0;
  413. static uint16_t last_timer_w = 0;
  414. uint16_t c_offsets[mkspd_COUNT] = {MK_C_OFFSET_UNMOD, MK_C_OFFSET_0, MK_C_OFFSET_1, MK_C_OFFSET_2};
  415. uint16_t c_intervals[mkspd_COUNT] = {MK_C_INTERVAL_UNMOD, MK_C_INTERVAL_0, MK_C_INTERVAL_1, MK_C_INTERVAL_2};
  416. uint16_t w_offsets[mkspd_COUNT] = {MK_W_OFFSET_UNMOD, MK_W_OFFSET_0, MK_W_OFFSET_1, MK_W_OFFSET_2};
  417. uint16_t w_intervals[mkspd_COUNT] = {MK_W_INTERVAL_UNMOD, MK_W_INTERVAL_0, MK_W_INTERVAL_1, MK_W_INTERVAL_2};
  418. void mousekey_task(void) {
  419. // report cursor and scroll movement independently
  420. report_mouse_t tmpmr = mouse_report;
  421. mouse_report.x = 0;
  422. mouse_report.y = 0;
  423. mouse_report.v = 0;
  424. mouse_report.h = 0;
  425. if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > c_intervals[mk_speed]) {
  426. mouse_report.x = tmpmr.x;
  427. mouse_report.y = tmpmr.y;
  428. }
  429. if ((tmpmr.h || tmpmr.v) && timer_elapsed(last_timer_w) > w_intervals[mk_speed]) {
  430. mouse_report.v = tmpmr.v;
  431. mouse_report.h = tmpmr.h;
  432. }
  433. if (has_mouse_report_changed(&mouse_report, &tmpmr) || should_mousekey_report_send(&mouse_report)) {
  434. mousekey_send();
  435. }
  436. memcpy(&mouse_report, &tmpmr, sizeof(tmpmr));
  437. }
  438. void adjust_speed(void) {
  439. uint16_t const c_offset = c_offsets[mk_speed];
  440. uint16_t const w_offset = w_offsets[mk_speed];
  441. if (mouse_report.x > 0) mouse_report.x = c_offset;
  442. if (mouse_report.x < 0) mouse_report.x = c_offset * -1;
  443. if (mouse_report.y > 0) mouse_report.y = c_offset;
  444. if (mouse_report.y < 0) mouse_report.y = c_offset * -1;
  445. if (mouse_report.h > 0) mouse_report.h = w_offset;
  446. if (mouse_report.h < 0) mouse_report.h = w_offset * -1;
  447. if (mouse_report.v > 0) mouse_report.v = w_offset;
  448. if (mouse_report.v < 0) mouse_report.v = w_offset * -1;
  449. // adjust for diagonals
  450. if (mouse_report.x && mouse_report.y) {
  451. mouse_report.x = times_inv_sqrt2(mouse_report.x);
  452. if (mouse_report.x == 0) {
  453. mouse_report.x = 1;
  454. }
  455. mouse_report.y = times_inv_sqrt2(mouse_report.y);
  456. if (mouse_report.y == 0) {
  457. mouse_report.y = 1;
  458. }
  459. }
  460. if (mouse_report.h && mouse_report.v) {
  461. mouse_report.h = times_inv_sqrt2(mouse_report.h);
  462. mouse_report.v = times_inv_sqrt2(mouse_report.v);
  463. }
  464. }
  465. void mousekey_on(uint8_t code) {
  466. uint16_t const c_offset = c_offsets[mk_speed];
  467. uint16_t const w_offset = w_offsets[mk_speed];
  468. uint8_t const old_speed = mk_speed;
  469. if (code == KC_MS_UP)
  470. mouse_report.y = c_offset * -1;
  471. else if (code == KC_MS_DOWN)
  472. mouse_report.y = c_offset;
  473. else if (code == KC_MS_LEFT)
  474. mouse_report.x = c_offset * -1;
  475. else if (code == KC_MS_RIGHT)
  476. mouse_report.x = c_offset;
  477. else if (code == KC_MS_WH_UP)
  478. mouse_report.v = w_offset;
  479. else if (code == KC_MS_WH_DOWN)
  480. mouse_report.v = w_offset * -1;
  481. else if (code == KC_MS_WH_LEFT)
  482. mouse_report.h = w_offset * -1;
  483. else if (code == KC_MS_WH_RIGHT)
  484. mouse_report.h = w_offset;
  485. else if (IS_MOUSEKEY_BUTTON(code))
  486. mouse_report.buttons |= 1 << (code - KC_MS_BTN1);
  487. else if (code == KC_MS_ACCEL0)
  488. mk_speed = mkspd_0;
  489. else if (code == KC_MS_ACCEL1)
  490. mk_speed = mkspd_1;
  491. else if (code == KC_MS_ACCEL2)
  492. mk_speed = mkspd_2;
  493. if (mk_speed != old_speed) adjust_speed();
  494. }
  495. void mousekey_off(uint8_t code) {
  496. # ifdef MK_MOMENTARY_ACCEL
  497. uint8_t const old_speed = mk_speed;
  498. # endif
  499. if (code == KC_MS_UP && mouse_report.y < 0)
  500. mouse_report.y = 0;
  501. else if (code == KC_MS_DOWN && mouse_report.y > 0)
  502. mouse_report.y = 0;
  503. else if (code == KC_MS_LEFT && mouse_report.x < 0)
  504. mouse_report.x = 0;
  505. else if (code == KC_MS_RIGHT && mouse_report.x > 0)
  506. mouse_report.x = 0;
  507. else if (code == KC_MS_WH_UP && mouse_report.v > 0)
  508. mouse_report.v = 0;
  509. else if (code == KC_MS_WH_DOWN && mouse_report.v < 0)
  510. mouse_report.v = 0;
  511. else if (code == KC_MS_WH_LEFT && mouse_report.h < 0)
  512. mouse_report.h = 0;
  513. else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0)
  514. mouse_report.h = 0;
  515. else if (IS_MOUSEKEY_BUTTON(code))
  516. mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1));
  517. # ifdef MK_MOMENTARY_ACCEL
  518. else if (code == KC_MS_ACCEL0)
  519. mk_speed = mkspd_DEFAULT;
  520. else if (code == KC_MS_ACCEL1)
  521. mk_speed = mkspd_DEFAULT;
  522. else if (code == KC_MS_ACCEL2)
  523. mk_speed = mkspd_DEFAULT;
  524. if (mk_speed != old_speed) adjust_speed();
  525. # endif
  526. }
  527. #endif /* #ifndef MK_3_SPEED */
  528. void mousekey_send(void) {
  529. mousekey_debug();
  530. uint16_t time = timer_read();
  531. if (mouse_report.x || mouse_report.y) last_timer_c = time;
  532. if (mouse_report.v || mouse_report.h) last_timer_w = time;
  533. host_mouse_send(&mouse_report);
  534. }
  535. void mousekey_clear(void) {
  536. mouse_report = (report_mouse_t){};
  537. mousekey_repeat = 0;
  538. mousekey_wheel_repeat = 0;
  539. mousekey_accel = 0;
  540. #ifdef MOUSEKEY_INERTIA
  541. mousekey_frame = 0;
  542. mousekey_x_inertia = 0;
  543. mousekey_y_inertia = 0;
  544. mousekey_x_dir = 0;
  545. mousekey_y_dir = 0;
  546. #endif
  547. }
  548. static void mousekey_debug(void) {
  549. if (!debug_mouse) return;
  550. print("mousekey [btn|x y v h](rep/acl): [");
  551. print_hex8(mouse_report.buttons);
  552. print("|");
  553. print_decs(mouse_report.x);
  554. print(" ");
  555. print_decs(mouse_report.y);
  556. print(" ");
  557. print_decs(mouse_report.v);
  558. print(" ");
  559. print_decs(mouse_report.h);
  560. print("](");
  561. print_dec(mousekey_repeat);
  562. print("/");
  563. print_dec(mousekey_accel);
  564. print(")\n");
  565. }
  566. report_mouse_t mousekey_get_report(void) {
  567. return mouse_report;
  568. }
  569. bool should_mousekey_report_send(report_mouse_t *mouse_report) {
  570. return mouse_report->x || mouse_report->y || mouse_report->v || mouse_report->h;
  571. }