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 */
1820enum 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