|
@@ -37,6 +37,13 @@ static void mousekey_debug(void);
|
|
|
static uint8_t mousekey_accel = 0;
|
|
|
static uint8_t mousekey_repeat = 0;
|
|
|
static uint8_t mousekey_wheel_repeat = 0;
|
|
|
+#ifdef MOUSEKEY_INERTIA
|
|
|
+static uint8_t mousekey_frame = 0; // track whether gesture is inactive, first frame, or repeating
|
|
|
+static int8_t mousekey_x_dir = 0; // -1 / 0 / 1 = left / neutral / right
|
|
|
+static int8_t mousekey_y_dir = 0; // -1 / 0 / 0 = up / neutral / down
|
|
|
+static int8_t mousekey_x_inertia = 0; // current velocity, limit +/- MOUSEKEY_TIME_TO_MAX
|
|
|
+static int8_t mousekey_y_inertia = 0; // ...
|
|
|
+#endif
|
|
|
#ifdef MK_KINETIC_SPEED
|
|
|
static uint16_t mouse_timer = 0;
|
|
|
#endif
|
|
@@ -76,6 +83,7 @@ uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
|
|
|
|
|
|
# ifndef MK_COMBINED
|
|
|
# ifndef MK_KINETIC_SPEED
|
|
|
+# ifndef MOUSEKEY_INERTIA
|
|
|
|
|
|
/* Default accelerated mode */
|
|
|
|
|
@@ -97,6 +105,53 @@ static uint8_t move_unit(void) {
|
|
|
return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
|
|
|
}
|
|
|
|
|
|
+# else // MOUSEKEY_INERTIA mode
|
|
|
+
|
|
|
+static int8_t move_unit(uint8_t axis) {
|
|
|
+ int16_t unit;
|
|
|
+
|
|
|
+ // handle X or Y axis
|
|
|
+ int8_t inertia, dir;
|
|
|
+ if (axis) {
|
|
|
+ inertia = mousekey_y_inertia;
|
|
|
+ dir = mousekey_y_dir;
|
|
|
+ } else {
|
|
|
+ inertia = mousekey_x_inertia;
|
|
|
+ dir = mousekey_x_dir;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mousekey_frame < 2) { // first frame(s): initial keypress moves one pixel
|
|
|
+ mousekey_frame = 1;
|
|
|
+ unit = dir * MOUSEKEY_MOVE_DELTA;
|
|
|
+ } else { // acceleration
|
|
|
+ // linear acceleration (is here for reference, but doesn't feel as good during use)
|
|
|
+ // unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * inertia) / mk_time_to_max;
|
|
|
+
|
|
|
+ // x**2 acceleration (quadratic, more precise for short movements)
|
|
|
+ int16_t percent = (inertia << 8) / mk_time_to_max;
|
|
|
+ percent = (percent * percent) >> 8;
|
|
|
+ if (inertia < 0) percent = -percent;
|
|
|
+
|
|
|
+ // unit = sign(inertia) + (percent of max speed)
|
|
|
+ if (inertia > 0)
|
|
|
+ unit = 1;
|
|
|
+ else if (inertia < 0)
|
|
|
+ unit = -1;
|
|
|
+ else
|
|
|
+ unit = 0;
|
|
|
+
|
|
|
+ unit = unit + ((mk_max_speed * percent) >> 8);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (unit > MOUSEKEY_MOVE_MAX)
|
|
|
+ unit = MOUSEKEY_MOVE_MAX;
|
|
|
+ else if (unit < -MOUSEKEY_MOVE_MAX)
|
|
|
+ unit = -MOUSEKEY_MOVE_MAX;
|
|
|
+ return unit;
|
|
|
+}
|
|
|
+
|
|
|
+# endif // end MOUSEKEY_INERTIA mode
|
|
|
+
|
|
|
static uint8_t wheel_unit(void) {
|
|
|
uint16_t unit;
|
|
|
if (mousekey_accel & (1 << 0)) {
|
|
@@ -213,6 +268,28 @@ static uint8_t wheel_unit(void) {
|
|
|
|
|
|
# endif /* #ifndef MK_COMBINED */
|
|
|
|
|
|
+# ifdef MOUSEKEY_INERTIA
|
|
|
+
|
|
|
+static int8_t calc_inertia(int8_t direction, int8_t velocity) {
|
|
|
+ // simulate acceleration and deceleration
|
|
|
+
|
|
|
+ // deceleration
|
|
|
+ if ((direction > -1) && (velocity < 0))
|
|
|
+ velocity = (velocity + 1) * (256 - MOUSEKEY_FRICTION) / 256;
|
|
|
+ else if ((direction < 1) && (velocity > 0))
|
|
|
+ velocity = velocity * (256 - MOUSEKEY_FRICTION) / 256;
|
|
|
+
|
|
|
+ // acceleration
|
|
|
+ if ((direction > 0) && (velocity < mk_time_to_max))
|
|
|
+ velocity++;
|
|
|
+ else if ((direction < 0) && (velocity > -mk_time_to_max))
|
|
|
+ velocity--;
|
|
|
+
|
|
|
+ return velocity;
|
|
|
+}
|
|
|
+
|
|
|
+# endif
|
|
|
+
|
|
|
void mousekey_task(void) {
|
|
|
// report cursor and scroll movement independently
|
|
|
report_mouse_t tmpmr = mouse_report;
|
|
@@ -222,6 +299,32 @@ void mousekey_task(void) {
|
|
|
mouse_report.v = 0;
|
|
|
mouse_report.h = 0;
|
|
|
|
|
|
+# ifdef MOUSEKEY_INERTIA
|
|
|
+
|
|
|
+ // if an animation is in progress and it's time for the next frame
|
|
|
+ if ((mousekey_frame) && timer_elapsed(last_timer_c) > ((mousekey_frame > 1) ? mk_interval : mk_delay * 10)) {
|
|
|
+ mousekey_x_inertia = calc_inertia(mousekey_x_dir, mousekey_x_inertia);
|
|
|
+ mousekey_y_inertia = calc_inertia(mousekey_y_dir, mousekey_y_inertia);
|
|
|
+
|
|
|
+ mouse_report.x = move_unit(0);
|
|
|
+ mouse_report.y = move_unit(1);
|
|
|
+
|
|
|
+ // prevent sticky "drift"
|
|
|
+ if ((!mousekey_x_dir) && (!mousekey_x_inertia)) tmpmr.x = 0;
|
|
|
+ if ((!mousekey_y_dir) && (!mousekey_y_inertia)) tmpmr.y = 0;
|
|
|
+
|
|
|
+ if (mousekey_frame < 2) mousekey_frame++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // reset if not moving and no movement keys are held
|
|
|
+ if ((!mousekey_x_dir) && (!mousekey_y_dir) && (!mousekey_x_inertia) && (!mousekey_y_inertia)) {
|
|
|
+ mousekey_frame = 0;
|
|
|
+ tmpmr.x = 0;
|
|
|
+ tmpmr.y = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+# else // default acceleration
|
|
|
+
|
|
|
if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) {
|
|
|
if (mousekey_repeat != UINT8_MAX) mousekey_repeat++;
|
|
|
if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1);
|
|
@@ -239,6 +342,9 @@ void mousekey_task(void) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+# endif // MOUSEKEY_INERTIA or not
|
|
|
+
|
|
|
if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) {
|
|
|
if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++;
|
|
|
if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1);
|
|
@@ -260,6 +366,7 @@ void mousekey_task(void) {
|
|
|
if (has_mouse_report_changed(&mouse_report, &tmpmr) || should_mousekey_report_send(&mouse_report)) {
|
|
|
mousekey_send();
|
|
|
}
|
|
|
+ // save the state for later
|
|
|
memcpy(&mouse_report, &tmpmr, sizeof(tmpmr));
|
|
|
}
|
|
|
|
|
@@ -270,6 +377,19 @@ void mousekey_on(uint8_t code) {
|
|
|
}
|
|
|
# endif /* #ifdef MK_KINETIC_SPEED */
|
|
|
|
|
|
+# ifdef MOUSEKEY_INERTIA
|
|
|
+
|
|
|
+ // initial keypress sets impulse and activates first frame of movement
|
|
|
+ if ((code == KC_MS_UP) || (code == KC_MS_DOWN)) {
|
|
|
+ mousekey_y_dir = (code == KC_MS_DOWN) ? 1 : -1;
|
|
|
+ if (mousekey_frame < 2) mouse_report.y = move_unit(1);
|
|
|
+ } else if ((code == KC_MS_LEFT) || (code == KC_MS_RIGHT)) {
|
|
|
+ mousekey_x_dir = (code == KC_MS_RIGHT) ? 1 : -1;
|
|
|
+ if (mousekey_frame < 2) mouse_report.x = move_unit(0);
|
|
|
+ }
|
|
|
+
|
|
|
+# else // no inertia
|
|
|
+
|
|
|
if (code == KC_MS_UP)
|
|
|
mouse_report.y = move_unit() * -1;
|
|
|
else if (code == KC_MS_DOWN)
|
|
@@ -278,6 +398,9 @@ void mousekey_on(uint8_t code) {
|
|
|
mouse_report.x = move_unit() * -1;
|
|
|
else if (code == KC_MS_RIGHT)
|
|
|
mouse_report.x = move_unit();
|
|
|
+
|
|
|
+# endif // inertia or not
|
|
|
+
|
|
|
else if (code == KC_MS_WH_UP)
|
|
|
mouse_report.v = wheel_unit();
|
|
|
else if (code == KC_MS_WH_DOWN)
|
|
@@ -297,6 +420,20 @@ void mousekey_on(uint8_t code) {
|
|
|
}
|
|
|
|
|
|
void mousekey_off(uint8_t code) {
|
|
|
+# ifdef MOUSEKEY_INERTIA
|
|
|
+
|
|
|
+ // key release clears impulse unless opposite direction is held
|
|
|
+ if ((code == KC_MS_UP) && (mousekey_y_dir < 1))
|
|
|
+ mousekey_y_dir = 0;
|
|
|
+ else if ((code == KC_MS_DOWN) && (mousekey_y_dir > -1))
|
|
|
+ mousekey_y_dir = 0;
|
|
|
+ else if ((code == KC_MS_LEFT) && (mousekey_x_dir < 1))
|
|
|
+ mousekey_x_dir = 0;
|
|
|
+ else if ((code == KC_MS_RIGHT) && (mousekey_x_dir > -1))
|
|
|
+ mousekey_x_dir = 0;
|
|
|
+
|
|
|
+# else // no inertia
|
|
|
+
|
|
|
if (code == KC_MS_UP && mouse_report.y < 0)
|
|
|
mouse_report.y = 0;
|
|
|
else if (code == KC_MS_DOWN && mouse_report.y > 0)
|
|
@@ -305,6 +442,9 @@ void mousekey_off(uint8_t code) {
|
|
|
mouse_report.x = 0;
|
|
|
else if (code == KC_MS_RIGHT && mouse_report.x > 0)
|
|
|
mouse_report.x = 0;
|
|
|
+
|
|
|
+# endif // inertia or not
|
|
|
+
|
|
|
else if (code == KC_MS_WH_UP && mouse_report.v > 0)
|
|
|
mouse_report.v = 0;
|
|
|
else if (code == KC_MS_WH_DOWN && mouse_report.v < 0)
|
|
@@ -476,6 +616,13 @@ void mousekey_clear(void) {
|
|
|
mousekey_repeat = 0;
|
|
|
mousekey_wheel_repeat = 0;
|
|
|
mousekey_accel = 0;
|
|
|
+#ifdef MOUSEKEY_INERTIA
|
|
|
+ mousekey_frame = 0;
|
|
|
+ mousekey_x_inertia = 0;
|
|
|
+ mousekey_y_inertia = 0;
|
|
|
+ mousekey_x_dir = 0;
|
|
|
+ mousekey_y_dir = 0;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
static void mousekey_debug(void) {
|