Skip to content

Commit 00e109c

Browse files
authored
Merge pull request #226 from rygwdn/float-acceleration
use interpolation to smoothly scale acceleration
2 parents fa91b0c + f1ce37f commit 00e109c

File tree

1 file changed

+38
-11
lines changed

1 file changed

+38
-11
lines changed

src/mouse.c

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
*/
1111

1212
#include "main.h"
13+
#include <math.h>
1314

1415
#define MACOS_SWITCH_MOVE_X 10
1516
#define MACOS_SWITCH_MOVE_COUNT 5
17+
#define ACCEL_POINTS 7
1618

1719
/* Check if our upcoming mouse movement would result in having to switch outputs */
1820
enum screen_pos_e is_screen_switch_needed(int position, int offset) {
@@ -39,13 +41,13 @@ int32_t move_and_keep_on_screen(int position, int offset) {
3941
return position + offset;
4042
}
4143

42-
/* Implement basic mouse acceleration and define your own curve.
43-
This one is probably sub-optimal, so let me know if you have a better one. */
44-
int32_t accelerate(int32_t offset) {
44+
/* Implement basic mouse acceleration based on actual 2D movement magnitude.
45+
Returns the acceleration factor to apply to both x and y components. */
46+
float calculate_mouse_acceleration_factor(int32_t offset_x, int32_t offset_y) {
4547
const struct curve {
4648
int value;
4749
float factor;
48-
} acceleration[7] = {
50+
} acceleration[ACCEL_POINTS] = {
4951
// 4 | *
5052
{2, 1}, // | *
5153
{5, 1.1}, // 3 |
@@ -56,16 +58,40 @@ int32_t accelerate(int32_t offset) {
5658
{70, 4.0}, // -------------------------------------------
5759
}; // 10 20 30 40 50 60 70
5860

61+
if (offset_x == 0 && offset_y == 0)
62+
return 1.0;
63+
5964
if (!global_state.config.enable_acceleration)
60-
return offset;
65+
return 1.0;
66+
67+
// Calculate the 2D movement magnitude
68+
const float movement_magnitude = sqrtf((float)(offset_x * offset_x) + (float)(offset_y * offset_y));
69+
70+
if (movement_magnitude <= acceleration[0].value)
71+
return acceleration[0].factor;
72+
73+
if (movement_magnitude >= acceleration[ACCEL_POINTS-1].value)
74+
return acceleration[ACCEL_POINTS-1].factor;
6175

62-
for (int i = 0; i < 7; i++) {
63-
if (abs(offset) < acceleration[i].value) {
64-
return offset * acceleration[i].factor;
76+
const struct curve *lower = NULL;
77+
const struct curve *upper = NULL;
78+
79+
for (int i = 0; i < ACCEL_POINTS-1; i++) {
80+
if (movement_magnitude < acceleration[i + 1].value) {
81+
lower = &acceleration[i];
82+
upper = &acceleration[i + 1];
83+
break;
6584
}
6685
}
6786

68-
return offset * acceleration[6].factor;
87+
// Should never happen, but just in case
88+
if (lower == NULL || upper == NULL)
89+
return 1.0;
90+
91+
const float interpolation_pos = (movement_magnitude - lower->value) /
92+
(upper->value - lower->value);
93+
94+
return lower->factor + interpolation_pos * (upper->factor - lower->factor);
6995
}
7096

7197
/* Returns LEFT if need to jump left, RIGHT if right, NONE otherwise */
@@ -78,8 +104,9 @@ enum screen_pos_e update_mouse_position(device_t *state, mouse_values_t *values)
78104
reduce_speed = MOUSE_ZOOM_SCALING_FACTOR;
79105

80106
/* Calculate movement */
81-
int offset_x = accelerate(values->move_x) * (current->speed_x >> reduce_speed);
82-
int offset_y = accelerate(values->move_y) * (current->speed_y >> reduce_speed);
107+
float acceleration_factor = calculate_mouse_acceleration_factor(values->move_x, values->move_y);
108+
int offset_x = round(values->move_x * acceleration_factor * (current->speed_x >> reduce_speed));
109+
int offset_y = round(values->move_y * acceleration_factor * (current->speed_y >> reduce_speed));
83110

84111
/* Determine if our upcoming movement would stay within the screen */
85112
enum screen_pos_e switch_direction = is_screen_switch_needed(state->pointer_x, offset_x);

0 commit comments

Comments
 (0)