Implement mouse movement acceleration and deceleration.

This commit is contained in:
László Monda
2017-11-24 13:00:05 +01:00
parent 0cb3c7e0ad
commit 210ef31f27
5 changed files with 74 additions and 106 deletions

View File

@@ -82,53 +82,16 @@ static parser_error_t parsePlayMacroAction(key_action_t *keyAction, config_buffe
static parser_error_t parseMouseAction(key_action_t *keyAction, config_buffer_t *buffer) static parser_error_t parseMouseAction(key_action_t *keyAction, config_buffer_t *buffer)
{ {
uint8_t mouseAction = ReadUInt8(buffer);
keyAction->type = KeyActionType_Mouse; keyAction->type = KeyActionType_Mouse;
memset(&keyAction->mouse, 0, sizeof keyAction->mouse);
switch (mouseAction) { uint8_t mouseAction = ReadUInt8(buffer);
case SerializedMouseAction_LeftClick: if (mouseAction > SerializedMouseAction_Last) {
keyAction->mouse.buttonActions = MouseButton_Left; return ParserError_InvalidSerializedMouseAction;
break;
case SerializedMouseAction_MiddleClick:
keyAction->mouse.buttonActions = MouseButton_Middle;
break;
case SerializedMouseAction_RightClick:
keyAction->mouse.buttonActions = MouseButton_Right;
break;
case SerializedMouseAction_MoveUp:
keyAction->mouse.moveActions = MouseMove_Up;
break;
case SerializedMouseAction_MoveDown:
keyAction->mouse.moveActions = MouseMove_Down;
break;
case SerializedMouseAction_MoveLeft:
keyAction->mouse.moveActions = MouseMove_Left;
break;
case SerializedMouseAction_MoveRight:
keyAction->mouse.moveActions = MouseMove_Right;
break;
case SerializedMouseAction_ScrollUp:
keyAction->mouse.scrollActions = MouseScroll_Up;
break;
case SerializedMouseAction_ScrollDown:
keyAction->mouse.scrollActions = MouseScroll_Down;
break;
case SerializedMouseAction_ScrollLeft:
keyAction->mouse.scrollActions = MouseScroll_Left;
break;
case SerializedMouseAction_ScrollRight:
keyAction->mouse.scrollActions = MouseScroll_Right;
break;
case SerializedMouseAction_Accelerate:
keyAction->mouse.speedActions = MouseSpeed_Accelerate;
break;
case SerializedMouseAction_Decelerate:
keyAction->mouse.speedActions = MouseSpeed_Decelerate;
break;
default:
return ParserError_InvalidSerializedMouseAction;
} }
memset(&keyAction->mouseAction, 0, sizeof keyAction->mouseAction);
keyAction->mouseAction = mouseAction;
return ParserError_Success; return ParserError_Success;
} }

View File

@@ -48,6 +48,10 @@
SerializedMouseAction_ScrollRight, SerializedMouseAction_ScrollRight,
SerializedMouseAction_Accelerate, SerializedMouseAction_Accelerate,
SerializedMouseAction_Decelerate, SerializedMouseAction_Decelerate,
SerializedMouseAction_Last = SerializedMouseAction_Decelerate,
SerializedMouseAction_Button_4,
SerializedMouseAction_Button_5,
SerializedMouseAction_Button_6,
} serialized_mouse_action_t; } serialized_mouse_action_t;
// Functions: // Functions:

View File

@@ -8,6 +8,7 @@
#include "lufa/HIDClassCommon.h" #include "lufa/HIDClassCommon.h"
#include "usb_composite_device.h" #include "usb_composite_device.h"
#include "module.h" #include "module.h"
#include "config_parser/parse_keymap.h"
// Typedefs: // Typedefs:
@@ -36,25 +37,6 @@
MouseButton_6 = 1 << 5, MouseButton_6 = 1 << 5,
} mouse_button_t; } mouse_button_t;
typedef enum {
MouseMove_Up = 1 << 0,
MouseMove_Down = 1 << 1,
MouseMove_Left = 1 << 2,
MouseMove_Right = 1 << 3,
} mouse_move_action_t;
typedef enum {
MouseSpeed_Accelerate = 1 << 0,
MouseSpeed_Decelerate = 1 << 1,
} mouse_speed_action_t;
typedef enum {
MouseScroll_Up = 1 << 0,
MouseScroll_Down = 1 << 1,
MouseScroll_Left = 1 << 2,
MouseScroll_Right = 1 << 3,
} mouse_scroll_t;
typedef struct { typedef struct {
uint8_t type; uint8_t type;
union { union {
@@ -64,12 +46,7 @@
uint8_t modifiers; uint8_t modifiers;
uint16_t scancode; uint16_t scancode;
} ATTR_PACKED keystroke; } ATTR_PACKED keystroke;
struct { serialized_mouse_action_t mouseAction;
mouse_button_t buttonActions;
mouse_scroll_t scrollActions;
mouse_move_action_t moveActions;
mouse_speed_action_t speedActions;
} ATTR_PACKED mouse;
struct { struct {
bool isToggle; bool isToggle;
uint8_t layer; uint8_t layer;

View File

@@ -332,23 +332,23 @@ key_action_t CurrentKeymap[LAYER_COUNT][SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE] =
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
// Row 2 // Row 2
{ .type = KeyActionType_Mouse, .mouse = { .buttonActions = MouseButton_4 }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_Button_4 },
{ .type = KeyActionType_Mouse, .mouse = { .moveActions = MouseMove_Up }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_MoveUp },
{ .type = KeyActionType_Mouse, .mouse = { .buttonActions = MouseButton_5 }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_Button_5 },
{ .type = KeyActionType_Mouse, .mouse = { .buttonActions = MouseButton_6 }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_Button_6 },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_Mouse, .mouse = { .scrollActions = MouseScroll_Up }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_ScrollUp },
// Row 3 // Row 3
{ .type = KeyActionType_Mouse, .mouse = { .moveActions = MouseMove_Left }}, { .type = KeyActionType_Mouse, .mouseAction= SerializedMouseAction_MoveLeft },
{ .type = KeyActionType_Mouse, .mouse = { .moveActions = MouseMove_Down }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_MoveDown },
{ .type = KeyActionType_Mouse, .mouse = { .moveActions = MouseMove_Right }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_MoveRight },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_Mouse, .mouse = { .scrollActions = MouseScroll_Down }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_ScrollDown },
// Row 4 // Row 4
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
@@ -391,9 +391,9 @@ key_action_t CurrentKeymap[LAYER_COUNT][SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE] =
// Row 3 // Row 3
{ .type = KeyActionType_SwitchLayer, .switchLayer = { .layer = LayerId_Mouse }}, { .type = KeyActionType_SwitchLayer, .switchLayer = { .layer = LayerId_Mouse }},
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_Mouse, .mouse = { .buttonActions = MouseButton_Right }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_RightClick },
{ .type = KeyActionType_Mouse, .mouse = { .buttonActions = MouseButton_Middle }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_MiddleClick },
{ .type = KeyActionType_Mouse, .mouse = { .buttonActions = MouseButton_Left }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_LeftClick },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
@@ -411,8 +411,8 @@ key_action_t CurrentKeymap[LAYER_COUNT][SLOT_COUNT][MAX_KEY_COUNT_PER_MODULE] =
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_LEFT_GUI }}, { .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_LEFT_GUI }},
{ .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_LEFT_ALT }}, { .type = KeyActionType_Keystroke, .keystroke = { .scancode = HID_KEYBOARD_SC_LEFT_ALT }},
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
{ .type = KeyActionType_Mouse, .mouse = { .speedActions = MouseSpeed_Decelerate }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_Decelerate },
{ .type = KeyActionType_Mouse, .mouse = { .speedActions = MouseSpeed_Accelerate }}, { .type = KeyActionType_Mouse, .mouseAction = SerializedMouseAction_Accelerate },
{ .type = KeyActionType_None }, { .type = KeyActionType_None },
} }
}, },

View File

@@ -14,6 +14,7 @@
#include "usb_report_updater.h" #include "usb_report_updater.h"
#include "timer.h" #include "timer.h"
#include "key_debouncer.h" #include "key_debouncer.h"
#include "config_parser/parse_keymap.h"
uint32_t UsbReportUpdateTime = 0; uint32_t UsbReportUpdateTime = 0;
static uint32_t elapsedTime; static uint32_t elapsedTime;
@@ -29,7 +30,9 @@ static float mouseScrollSpeed = 0.1;
static bool isMouseMoving; static bool isMouseMoving;
static bool wasMouseMoving; static bool wasMouseMoving;
void processMouseAction(key_action_t *action) static bool activeMouseStates[SerializedMouseAction_Last];
void processMouseActions()
{ {
static float mouseMoveCurrentSpeed; static float mouseMoveCurrentSpeed;
@@ -37,17 +40,22 @@ void processMouseAction(key_action_t *action)
mouseMoveCurrentSpeed = mouseMoveInitialSpeed; mouseMoveCurrentSpeed = mouseMoveInitialSpeed;
} }
if (action->mouse.moveActions) { bool isMoveAction = activeMouseStates[SerializedMouseAction_MoveUp] ||
isMouseMoving = true; activeMouseStates[SerializedMouseAction_MoveDown] ||
activeMouseStates[SerializedMouseAction_MoveLeft] ||
activeMouseStates[SerializedMouseAction_MoveRight];
float targetSpeed; float targetSpeed;
if (action->mouse.speedActions & MouseSpeed_Accelerate) { if (activeMouseStates[SerializedMouseAction_Accelerate]) {
targetSpeed = mouseMoveAcceleratedSpeed; targetSpeed = mouseMoveAcceleratedSpeed;
} else if (action->mouse.speedActions & MouseSpeed_Decelerate) { } else if (activeMouseStates[SerializedMouseAction_Decelerate]) {
targetSpeed = mouseMoveDeceleratedSpeed; targetSpeed = mouseMoveDeceleratedSpeed;
} else { } else if (isMoveAction) {
targetSpeed = mouseMoveBaseSpeed; targetSpeed = mouseMoveBaseSpeed;
} }
if (isMoveAction) {
isMouseMoving = true;
if (mouseMoveCurrentSpeed < targetSpeed) { if (mouseMoveCurrentSpeed < targetSpeed) {
mouseMoveCurrentSpeed += mouseMoveBaseAcceleration * elapsedTime / 1000; mouseMoveCurrentSpeed += mouseMoveBaseAcceleration * elapsedTime / 1000;
@@ -63,35 +71,40 @@ void processMouseAction(key_action_t *action)
uint16_t distance = mouseMoveCurrentSpeed * elapsedTime / 10; uint16_t distance = mouseMoveCurrentSpeed * elapsedTime / 10;
if (action->mouse.moveActions & MouseMove_Left) { if (activeMouseStates[SerializedMouseAction_MoveLeft]) {
ActiveUsbMouseReport->x = -distance; ActiveUsbMouseReport->x = -distance;
} else if (action->mouse.moveActions & MouseMove_Right) { } else if (activeMouseStates[SerializedMouseAction_MoveRight]) {
ActiveUsbMouseReport->x = distance; ActiveUsbMouseReport->x = distance;
} }
if (action->mouse.moveActions & MouseMove_Up) { if (activeMouseStates[SerializedMouseAction_MoveUp]) {
ActiveUsbMouseReport->y = -distance; ActiveUsbMouseReport->y = -distance;
} else if (action->mouse.moveActions & MouseMove_Down) { } else if (activeMouseStates[SerializedMouseAction_MoveDown]) {
ActiveUsbMouseReport->y = distance; ActiveUsbMouseReport->y = distance;
} }
} }
bool isScrollAction = activeMouseStates[SerializedMouseAction_ScrollUp] ||
activeMouseStates[SerializedMouseAction_ScrollDown] ||
activeMouseStates[SerializedMouseAction_ScrollLeft] ||
activeMouseStates[SerializedMouseAction_ScrollRight];
static float mouseScrollDistanceSum = 0; static float mouseScrollDistanceSum = 0;
if (action->mouse.scrollActions) { if (isScrollAction) {
mouseScrollDistanceSum += mouseScrollSpeed; mouseScrollDistanceSum += mouseScrollSpeed;
float mouseScrollDistanceIntegerSum; float mouseScrollDistanceIntegerSum;
float mouseScrollDistanceFractionSum = modff(mouseScrollDistanceSum, &mouseScrollDistanceIntegerSum); float mouseScrollDistanceFractionSum = modff(mouseScrollDistanceSum, &mouseScrollDistanceIntegerSum);
if (mouseScrollDistanceIntegerSum) { if (mouseScrollDistanceIntegerSum) {
if (action->mouse.scrollActions & MouseScroll_Up) { if (activeMouseStates[SerializedMouseAction_ScrollUp]) {
ActiveUsbMouseReport->wheelX = mouseScrollDistanceIntegerSum; ActiveUsbMouseReport->wheelX = mouseScrollDistanceIntegerSum;
} else if (action->mouse.scrollActions & MouseScroll_Down) { } else if (activeMouseStates[SerializedMouseAction_ScrollDown]) {
ActiveUsbMouseReport->wheelX = -mouseScrollDistanceIntegerSum; ActiveUsbMouseReport->wheelX = -mouseScrollDistanceIntegerSum;
} }
if (action->mouse.scrollActions & MouseScroll_Right) { if (activeMouseStates[SerializedMouseAction_ScrollRight]) {
ActiveUsbMouseReport->wheelY = mouseScrollDistanceIntegerSum; ActiveUsbMouseReport->wheelY = mouseScrollDistanceIntegerSum;
} else if (action->mouse.scrollActions & MouseScroll_Left) { } else if (activeMouseStates[SerializedMouseAction_ScrollLeft]) {
ActiveUsbMouseReport->wheelY = -mouseScrollDistanceIntegerSum; ActiveUsbMouseReport->wheelY = -mouseScrollDistanceIntegerSum;
} }
mouseScrollDistanceSum = mouseScrollDistanceFractionSum; mouseScrollDistanceSum = mouseScrollDistanceFractionSum;
@@ -100,7 +113,15 @@ void processMouseAction(key_action_t *action)
mouseScrollDistanceSum = 0; mouseScrollDistanceSum = 0;
} }
ActiveUsbMouseReport->buttons |= action->mouse.buttonActions; if (activeMouseStates[SerializedMouseAction_LeftClick]) {
ActiveUsbMouseReport->buttons |= MouseButton_Left;
}
if (activeMouseStates[SerializedMouseAction_MiddleClick]) {
ActiveUsbMouseReport->buttons |= MouseButton_Middle;
}
if (activeMouseStates[SerializedMouseAction_RightClick]) {
ActiveUsbMouseReport->buttons |= MouseButton_Right;
}
} }
static uint8_t basicScancodeIndex = 0; static uint8_t basicScancodeIndex = 0;
@@ -139,7 +160,7 @@ void applyKeyAction(key_state_t *keyState, key_action_t *action)
} }
break; break;
case KeyActionType_Mouse: case KeyActionType_Mouse:
processMouseAction(action); activeMouseStates[action->mouseAction] = true;
break; break;
case KeyActionType_SwitchKeymap: case KeyActionType_SwitchKeymap:
if (!keyState->previous && keyState->current) { if (!keyState->previous && keyState->current) {
@@ -157,6 +178,7 @@ static secondary_role_t secondaryRole;
void updateActiveUsbReports(void) void updateActiveUsbReports(void)
{ {
memset(activeMouseStates, 0, SerializedMouseAction_Last);
wasMouseMoving = isMouseMoving; wasMouseMoving = isMouseMoving;
isMouseMoving = false; isMouseMoving = false;
@@ -243,6 +265,8 @@ void updateActiveUsbReports(void)
} }
} }
processMouseActions();
// When a layer switcher key gets pressed along with another key that produces some modifiers // When a layer switcher key gets pressed along with another key that produces some modifiers
// and the accomanying key gets released then keep the related modifiers active a long as the // and the accomanying key gets released then keep the related modifiers active a long as the
// layer switcher key stays pressed. Useful for Alt+Tab keymappings and the like. // layer switcher key stays pressed. Useful for Alt+Tab keymappings and the like.