Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement caret mode #344

Merged
merged 6 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions right/src/caret_config.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "caret_config.h"
#include "arduino_hid/ConsumerAPI.h"
#include "arduino_hid/SystemAPI.h"

caret_configuration_t caretMediaMode = {
.axisActions = { //axis array
{ // horizontal axis
.positiveAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Media, .scancode = MEDIA_NEXT }},
.negativeAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Media, .scancode = MEDIA_PLAY_PAUSE }},
},
{ // vertical axis
.positiveAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Media, .scancode = MEDIA_VOLUME_UP }},
.negativeAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Media, .scancode = MEDIA_VOLUME_DOWN }},
}
}
};


caret_configuration_t caretCaretMode = {
.axisActions = { //axis array
{ // horizontal axis
.positiveAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Basic, .scancode = HID_KEYBOARD_SC_RIGHT_ARROW }},
.negativeAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Basic, .scancode = HID_KEYBOARD_SC_LEFT_ARROW }},
},
{ // vertical axis
.positiveAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Basic, .scancode = HID_KEYBOARD_SC_UP_ARROW }},
.negativeAction = { .type = KeyActionType_Keystroke, .keystroke = { .keystrokeType = KeystrokeType_Basic, .scancode = HID_KEYBOARD_SC_DOWN_ARROW }},
}
}
};

caret_configuration_t* GetModuleCaretConfiguration(int8_t moduleId, navigation_mode_t mode) {
switch (mode) {
case NavigationMode_Caret:
return &caretCaretMode;
case NavigationMode_Media:
return &caretMediaMode;
default:
return &caretCaretMode;
}
}

33 changes: 33 additions & 0 deletions right/src/caret_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef __CARET_CONFIG_H__
#define __CARET_CONFIG_H__

// Includes:

#include "key_action.h"
#include "module.h"

// Typedefs:

typedef enum {
CaretAxis_Horizontal = 0,
CaretAxis_Vertical = 1,
CaretAxis_Count = 2,
CaretAxis_Inactive = CaretAxis_Count,
CaretAxis_None = CaretAxis_Count,
} caret_axis_t;

typedef struct {
key_action_t negativeAction;
key_action_t positiveAction;
} caret_dir_action_t;

typedef struct {
caret_dir_action_t axisActions[CaretAxis_Count];
} caret_configuration_t;


// Functions:

caret_configuration_t* GetModuleCaretConfiguration(int8_t moduleId, navigation_mode_t mode);

#endif
97 changes: 92 additions & 5 deletions right/src/mouse_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "slave_scheduler.h"
#include "layer_switcher.h"
#include "usb_report_updater.h"
#include "caret_config.h"
#include "keymap.h"

static uint32_t mouseUsbReportUpdateTime = 0;
static uint32_t mouseElapsedTime;
Expand Down Expand Up @@ -232,11 +234,18 @@ static void processTouchpadActions() {
}
}

//todo: break this function into parts
void processModuleActions(uint8_t moduleId, float x, float y) {
module_configuration_t *moduleConfiguration = GetModuleConfiguration(moduleId);
navigation_mode_t navigationMode = moduleConfiguration->navigationModes[ActiveLayer];
int16_t yInversion = moduleId == ModuleId_KeyClusterLeft || moduleId == ModuleId_TouchpadRight ? -1 : 1;
static caret_axis_t caretAxis = CaretAxis_None;
static key_state_t caretFakeKeystate = {};
static key_action_t* caretAction = &CurrentKeymap[0][0][0];
int8_t scrollSpeedDivisor = 8;
float caretSpeedDivisor = 16;
float caretSkewStrength = 0.5f;

float speed = computeModuleSpeed(x, y, moduleId);

static float xFractionRemainder = 0.0f;
Expand All @@ -246,7 +255,8 @@ void processModuleActions(uint8_t moduleId, float x, float y) {

if (moduleId == ModuleId_KeyClusterLeft) {
scrollSpeedDivisor = 1;
speed = navigationMode == NavigationMode_Scroll ? 1 : 5;
caretSpeedDivisor = 1;
speed = navigationMode == NavigationMode_Scroll ? 5 : 1;
}

switch (navigationMode) {
Expand All @@ -260,7 +270,7 @@ void processModuleActions(uint8_t moduleId, float x, float y) {
break;
}
case NavigationMode_Scroll: {
if (moduleId == ModuleId_KeyClusterLeft) {
if (moduleId == ModuleId_KeyClusterLeft && (x != 0 || y != 0)) {
xFractionRemainder = 0;
yFractionRemainder = 0;
}
Expand All @@ -272,10 +282,87 @@ void processModuleActions(uint8_t moduleId, float x, float y) {
ActiveUsbMouseReport->wheelY += yInversion*yIntegerPart;
break;
}
case NavigationMode_Media:
case NavigationMode_Caret: {
break;
}
case NavigationMode_Media: {
//optimize this out if nothing is going on
if (x == 0 && y == 0 && caretAxis == CaretAxis_None) {
break;
}
caret_configuration_t* currentCaretConfig = GetModuleCaretConfiguration(moduleId, navigationMode);

//unlock axis if inactive for some time and re-activate tick trashold`
if (x != 0 || y != 0) {
static uint16_t lastUpdate = 0;

if (CurrentTime - lastUpdate > 500 && caretAxis != CaretAxis_None) {
xFractionRemainder = 0;
yFractionRemainder = 0;
caretAxis = CaretAxis_None;
}
lastUpdate = CurrentTime;
}

// caretAxis tries to lock to one direction, therefore we "skew" the other one
float caretXModeMultiplier;
float caretYModeMultiplier;

if(caretAxis == CaretAxis_None) {
// if no axis is locked atm, tweak trigger sensitivity depending on module
if (moduleId == ModuleId_KeyClusterLeft) {
caretXModeMultiplier = caretSkewStrength;
caretYModeMultiplier = caretSkewStrength;
} else {
caretXModeMultiplier = 1.0f;
caretYModeMultiplier = 1.0f;
}
} else {
caretXModeMultiplier = caretAxis == CaretAxis_Horizontal ? 1.0f : caretSkewStrength;
caretYModeMultiplier = caretAxis == CaretAxis_Vertical ? 1.0f : caretSkewStrength;
}

xFractionRemainder += x * speed / caretSpeedDivisor * caretXModeMultiplier;
yFractionRemainder += y * speed / caretSpeedDivisor * caretYModeMultiplier;


//If there is an ongoing action, just handle that action via a fake state. Ensure that full lifecycle of a key gets executed.
if (caretFakeKeystate.current || caretFakeKeystate.previous) {
bool tmp = caretFakeKeystate.current;
caretFakeKeystate.current = !caretFakeKeystate.previous;
caretFakeKeystate.previous = tmp;
ApplyKeyAction(&caretFakeKeystate, caretAction, caretAction);
}
//If we want to start a new action (new "tick")
else {
// determine current axis properties and setup indirections for easier handling
caret_axis_t axisCandidate = caretAxis == CaretAxis_Inactive ? CaretAxis_Vertical : caretAxis;
float* axisFractionRemainders [CaretAxis_Count] = {&xFractionRemainder, &yFractionRemainder};
float axisIntegerParts [CaretAxis_Count] = { 0, 0 };

modff(xFractionRemainder, &axisIntegerParts[CaretAxis_Horizontal]);
modff(yFractionRemainder, &axisIntegerParts[CaretAxis_Vertical]);

// pick axis to apply action on, if possible - check previously active axis first
if ( axisIntegerParts[axisCandidate] != 0 ) {
axisCandidate = axisCandidate;
} else if ( axisIntegerParts[1 - axisCandidate] != 0 ) {
axisCandidate = 1 - axisCandidate;
} else {
axisCandidate = CaretAxis_None;
}

// handle the action
if ( axisCandidate < CaretAxis_Count ) {
caretAxis = axisCandidate;
float sgn = axisIntegerParts[axisCandidate] > 0 ? 1 : -1;
uint8_t currentAxisInversion = axisCandidate == CaretAxis_Vertical ? yInversion : 1;
*axisFractionRemainders[1 - axisCandidate] = 0.0f;
*axisFractionRemainders[axisCandidate] -= sgn;
caret_dir_action_t* dirActions = &currentCaretConfig->axisActions[caretAxis];
caretAction = sgn*currentAxisInversion > 0 ? &dirActions->positiveAction : &dirActions->negativeAction;
caretFakeKeystate.current = true;
ApplyKeyAction(&caretFakeKeystate, caretAction, caretAction);
}
}
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions right/src/usb_report_updater.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static void applyKeystroke(key_state_t *keyState, key_action_t *action, key_acti
}
}

static void applyKeyAction(key_state_t *keyState, key_action_t *action, key_action_t *actionBase, uint8_t slotId, uint8_t keyId)
void ApplyKeyAction(key_state_t *keyState, key_action_t *action, key_action_t *actionBase)
{
switch (action->type) {
case KeyActionType_Keystroke:
Expand Down Expand Up @@ -362,7 +362,7 @@ static void updateActiveUsbReports(void)
applyLayerHolds(keyState, actionBase);

//apply active-layer action
applyKeyAction(keyState, action, actionBase, slotId, keyId);
ApplyKeyAction(keyState, action, actionBase);

keyState->previous = keyState->current;
}
Expand Down
3 changes: 3 additions & 0 deletions right/src/usb_report_updater.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "layer.h"
#include "config_parser/parse_keymap.h"
#include "key_states.h"
#include "key_action.h"

// Macros:

Expand Down Expand Up @@ -40,5 +42,6 @@
// Functions:

void UpdateUsbReports(void);
void ApplyKeyAction(key_state_t *keyState, key_action_t *action, key_action_t *actionBase);

#endif