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

[core][new feature]Pointing device modes #21426

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Progress...
  • Loading branch information
Alabastard-64 committed Feb 1, 2025
commit 605296f1af8fbfcff585b637fbaad1f25e8c60cd
2 changes: 1 addition & 1 deletion quantum/keymap_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ __attribute__((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key
}
#endif // DIP_SWITCH_MAP_ENABLE

#if defined(POINTING_MODE_MAP_ENABLE)
#ifdef POINTING_MODE_MAP_ENABLE
else if (key.row == KEYLOC_POINTING_MODE && key.col < ((pointing_mode_map_count() << 2) | 0x03)) {
return keycode_at_pointing_mode_map_location(key.col);
}
Expand Down
2 changes: 1 addition & 1 deletion quantum/keymap_introspection.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ __attribute__((weak)) const key_override_t* key_override_get(uint16_t key_overri
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pointing mode mapping

#if defined(POINTING_MODE_MAP_ENABLE)
#ifdef POINTING_MODE_MAP_ENABLE

# define POINTING_MODE_MAP_COUNT_RAW (uint8_t)(sizeof(pointing_mode_maps) / ((POINTING_MODE_NUM_DIRECTIONS) * sizeof(uint16_t)))

Expand Down
213 changes: 168 additions & 45 deletions quantum/pointing_device/pointing_device_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,21 @@ uint8_t pointing_mode_get_precision(void) {
void pointing_mode_set_precision(uint8_t precision) {
if (precision > POINTING_MODE_PRECISION_MAX || !precision) {
pointing_mode_devices[active_device_id].precision = 1;
return;
} else {
pointing_mode_devices[active_device_id].precision = precision;
}
pointing_mode_devices[active_device_id].precision = precision;
}

static uint8_t pointing_mode_get_type(uint8_t mode_id) {
uint8_t mode_type = PMT_NONE;

mode_type = pointing_mode_get_type_kb(mode_id);
if (mode_type) return mode_type;

mode_type = pointing_mode_get_type_user(mode_id);
if (mode_type) return mode_type;

return PMT_4WAY;
}

/**
Expand Down Expand Up @@ -317,23 +329,49 @@ static uint8_t pointing_mode_update_divisor(void) {
*
* Determines direction based on axis with largest magnitude
*
* NOTE: Defaults to PD_DOWN
* NOTE: Defaults to PMD_DOWN
*
* @return direction uint8_t
*/
static uint8_t pointing_mode_update_direction(void) {
if (abs(pointing_mode_devices[active_device_id].x) > abs(pointing_mode_devices[active_device_id].y)) {
if (pointing_mode_devices[active_device_id].x > 0) {
return PD_RIGHT;
} else {
return PD_LEFT;
}
} else {
if (pointing_mode_devices[active_device_id].y > 0) {
return PD_DOWN;
} else {
return PD_UP;
}
# if POINTING_MODE_THRESHOLD > 0
if(abs(pointing_mode_devices[active_device_id].x) + abs(pointing_mode_devices[active_device_id].y) > POINTING_MODE_THRESHOLD) {
return PMD_NONE
}
# endif
switch (pointing_mode_get_type(pointing_mode_get_mode() & PMT_MODES) {
case PMT_4WAY:
if (abs(pointing_mode_devices[active_device_id].x) > abs(pointing_mode_devices[active_device_id].y)) {
if (pointing_mode_devices[active_device_id].x > 0) {
return PMD_RIGHT;
} else {
return PMD_LEFT;
}
} else {
if (pointing_mode_devices[active_device_id].y > 0) {
return PMD_DOWN;
} else {
return PMD_UP;
}
}
break;
case PMT_DPAD:
uint8_t dir_out = PMD_NONE;
if ((abs(pointing_mode_devices[active_device_id].x) << 1) > abs(pointing_mode_devices[active_device_id].y) {
if (pointing_mode_devices[active_device_id].x > 0) {
dir_out &= PMD_RIGHT;
} else {
dir_out &= PMD_LEFT;
}
}
if ((abs(pointing_mode_devices[active_device_id].y) << 1) > abs(pointing_mode_devices[active_device_id].x) {
if (pointing_mode_devices[active_device_id].y > 0) {
dir_out &= PMD_DOWN;
} else {
dir_out &= PMD_UP;
}
}
return dir_out;
}
}

Expand Down Expand Up @@ -380,18 +418,20 @@ uint8_t current_pointing_mode_divisor(void) {
*/
static void pointing_tap_keycodes_raw(uint16_t* pm_keycodes) {
int16_t count = 0;
uint8_t dir = current_pointing_mode_direction();
uint8_t key = 0;

switch (dir) {
case PD_DOWN ... PD_UP:
switch (current_pointing_mode_direction()) {
case PMD_DOWN ... PMD_UP:
count = divisor_divide16(pointing_mode_devices[active_device_id].y);
if (!count) return; // exit if accumulated y is too low
key = count > 0? PMK_DOWN:PMK_UP;
pointing_mode_devices[active_device_id].y -= divisor_multiply16(count);
pointing_mode_devices[active_device_id].x = 0;
break;
case PD_LEFT ... PD_RIGHT:
case PMD_LEFT ... PMD_RIGHT:
count = divisor_divide16(pointing_mode_devices[active_device_id].x);
if (!count) return; // exit if accumulated x is too low
key = count > 0? PMK_RIGHT:PMK_LEFT;
pointing_mode_devices[active_device_id].x -= divisor_multiply16(count);
pointing_mode_devices[active_device_id].y = 0;
break;
Expand All @@ -402,7 +442,7 @@ static void pointing_tap_keycodes_raw(uint16_t* pm_keycodes) {
// tap codes
uint8_t taps = clamp_uint_16_to_8((uint16_t)abs(count));
do {
tap_code16_delay(pm_keycodes[dir], POINTING_MODE_TAP_DELAY);
tap_code16_delay(pm_keycodes[key], POINTING_MODE_TAP_DELAY);
} while (--taps);
}

Expand Down Expand Up @@ -434,36 +474,91 @@ void pointing_tap_codes(uint16_t kc_left, uint16_t kc_down, uint16_t kc_up, uint
*/
# ifdef POINTING_MODE_MAP_ENABLE
static void pointing_exec_mapping(uint8_t map_id) {
int16_t count = 0;
uint8_t dir = current_pointing_mode_direction();

switch (dir) {
case PD_DOWN ... PD_UP:
count = divisor_divide16(pointing_mode_devices[active_device_id].y);
if (!count) return; // exit if accumulated y is too low
pointing_mode_devices[active_device_id].y -= divisor_multiply16(count);
pointing_mode_devices[active_device_id].x = 0;
break;
case PD_LEFT ... PD_RIGHT:
count = divisor_divide16(pointing_mode_devices[active_device_id].x);
if (!count) return; // exit if accumulated x is too low
pointing_mode_devices[active_device_id].x -= divisor_multiply16(count);
pointing_mode_devices[active_device_id].y = 0;
static uint16_t prev_key[] = {0, 0};

int16_t count[] = {0, 0};
uint8_t key[] = {0, 0};
uint8_t mode_type = pointing_mode_get_type(pointing_mode_get_mode());
switch (mode_type & PMT_MODES) {
case PMT_4WAY:
switch (current_pointing_mode_direction()) {
case PMD_DOWN ... PMD_UP:
count[0] = divisor_divide16(pointing_mode_devices[active_device_id].y);
if (!count[0]) return; // exit if accumulated y is too low
key[0] = count[0] > 0? PMK_DOWN:PMK_UP;
pointing_mode_devices[active_device_id].y = 0;
pointing_mode_devices[active_device_id].x = 0;
break;
case PMD_LEFT ... PMD_RIGHT:
count[0] = divisor_divide16(pointing_mode_devices[active_device_id].x);
if (!count[0]) return; // exit if accumulated x is too low
key[0] = count[0] > 0? PMK_RIGHT:PMK_LEFT;
pointing_mode_devices[active_device_id].x = 0;
pointing_mode_devices[active_device_id].y = 0;
break;
}
break;
case PMT_DPAD:
uint8_t dir = current_pointing_mode_direction();
if(dir & PMD_VERT) {
count[0] = divisor_divide16(pointing_mode_devices[active_device_id].y);
pointing_mode_devices[active_device_id].y = 0;
key[0] = count[0] > 0? PMK_DOWN:PMK_UP;
}
if(dir & PMD_HORI) {
count[1] = divisor_divide16(pointing_mode_devices[active_device_id].x);
pointing_mode_devices[active_device_id].x = 0;
key[1] = count[1] > 0? PMK_RIGHT:PMK_LEFT;
}
}

// tap codes
uint8_t taps = clamp_uint_16_to_8((uint16_t)abs(count));
do {
action_exec(MAKE_POINTING_MODE_EVENT(map_id, dir, true));
switch(mode_type & PMT_OPTS){
case PMT_TAP:
if(count[0]) {
uint8_t taps = clamp_uint_16_to_8((uint16_t)abs(count[0]));
do {
action_exec(MAKE_POINTING_MODE_EVENT(map_id, key[0], true));
# if POINTING_MODE_TAP_DELAY > 0
wait_ms(POINTING_MODE_TAP_DELAY);
wait_ms(POINTING_MODE_TAP_DELAY);
# endif // POINTING_MODE_TAP_DELAY > 0
action_exec(MAKE_POINTING_MODE_EVENT(map_id, dir, false));
} while (--taps);
action_exec(MAKE_POINTING_MODE_EVENT(map_id, key[0], false));
} while (--taps);
}
if(count[1]) {
uint8_t taps = clamp_uint_16_to_8((uint16_t)abs(count[1]));
do {
action_exec(MAKE_POINTING_MODE_EVENT(map_id, key[1], true));
# if POINTING_MODE_TAP_DELAY > 0
wait_ms(POINTING_MODE_TAP_DELAY);
# endif // POINTING_MODE_TAP_DELAY > 0
action_exec(MAKE_POINTING_MODE_EVENT(map_id, key[1], false));
} while (--taps);
}
break;
case PMT_HOLD:
if(count[0]) {
action_exec(MAKE_POINTING_MODE_EVENT(map_id, prev_key[0], false));
if(prev_key[0] != key[0]) {
action_exec(MAKE_POINTING_MODE_EVENT(map_id, key[0], true));
prev_key[0] = key[0];
} else {
prev_key[0] = 0;
}
}
if(count[1]) {
action_exec(MAKE_POINTING_MODE_EVENT(map_id, prev_key[1], false));
if(prev_key[1] != key[1]) {
action_exec(MAKE_POINTING_MODE_EVENT(map_id, key[1], true));
prev_key[1] = key[1];
} else {
prev_key[1] = 0;
}
}
}
}
# endif



/**
* @brief Core function to handle pointing mode task
*
Expand Down Expand Up @@ -566,7 +661,7 @@ __attribute__((weak)) bool process_pointing_mode_kb(pointing_mode_device_t point
}

/**
* @brief Weak function for user level adding of pointing mode divisors
* @brief Weakly defined function adding of pointing mode divisors at user level
*
* Takes in mode id and direction allowing for divisor values to be
* determined based on these parameters
Expand All @@ -581,7 +676,7 @@ __attribute__((weak)) uint8_t get_pointing_mode_divisor_user(uint8_t mode_id, ui
}

/**
* @brief Weak function for user level adding of pointing mode divisors
* @brief Weakly defined function adding of pointing mode divisors at keyboard level
*
* Takes in mode id and direction allowing for divisor values to be
* determined based on these parameters
Expand All @@ -595,4 +690,32 @@ __attribute__((weak)) uint8_t get_pointing_mode_divisor_kb(uint8_t mode_id, uint
return 0; // continue processing
}

/**
* @brief Weakly defined function for setting pointing mode type at the user level
*
* Takes in mode id and returns current pointing mode type (PMT_4WAY, PMT_DPAD).
* Also mode options may be added to the mode type (PMT_HOLD)
*
* @params mode_id uint8_t
*
* @return pointing_mode_type uint8_t
*/
__attribute__((weak)) uint8_t get_pointing_mode_type_user(uint8_t mode_id) {
return PMT_NONE; // continue processing
}

/**
* @brief Weakly defined function for setting pointing mode type at the user level
*
* Takes in mode id and returns current pointing mode type (PMT_4WAY, PMT_DPAD).
* Also mode options may be added to the mode type (PMT_HOLD)
*
* @params mode_id uint8_t
*
* @return pointing_mode_type uint8_t
*/
__attribute__((weak)) uint8_t get_pointing_mode_type_kb(uint8_t mode_id, uint8_t direction) {
return PMT_NONE; // continue processing
}

#endif // POINTING_DEVICE_POINTING_MODES_ENABLE
53 changes: 37 additions & 16 deletions quantum/pointing_device/pointing_device_modes.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
#endif
#define POINTING_MODE_NUM_DIRECTIONS 4

#ifndef POINTING_MODE_THRESHOLD
# define POINTING_MODE_THRESHOLD 0
#endif

// default divisors
#ifndef POINTING_MODE_DEFAULT_DIVISOR
# define POINTING_MODE_DEFAULT_DIVISOR 64
Expand Down Expand Up @@ -82,15 +86,33 @@

/* enums */
enum pointing_mode_directions {
// PD_NONE = 0b0000
PD_DOWN = 0, // 0b1001
PD_UP = 1, // 0b0001
PD_LEFT = 2, // 0b0110
PD_RIGHT = 3, // 0b0010
PD_DNLFT = 4, // 0b1111
PD_DNRGT = 5, // 0b1011
PD_UPLFT = 6, // 0b0111
PD_UPRGT = 7 // 0b0011
PMD_NONE = 0x00, // [0000]
PMD_DOWN = 0x01, // [0001]
PMD_UP = 0x02, // [0010]
PMD_LEFT = 0x04, // [0100]
PMD_RIGHT = 0x08, // [1000]
PMD_VERT = 0x03, // [0011]
PMD_HORI = 0x0C // [1100]
//PMD_DNLT = 0x05, // [0101]
//PMD_UPLT = 0x06, // [0110]
//PMD_DNRT = 0x09, // [1001]
//PMD_UPRT = 0x0A // [1010]
};

enum pointing_mode_4_key_directions {
PMK_UP = 0,
PMK_LEFT = 1,
PMK_RIGHT = 2,
PMK_DOWN = 3
};

enum pointing_mode_types {
PMT_4WAY = 0x00,
PMT_DPAD = 0x01,
PMT_MODES = 0x0F,
PMT_TAP = 0x00,
PMT_HOLD = 0x10,
PMT_OPTS = 0xF0
};

enum pointing_mode_devices {
Expand Down Expand Up @@ -119,16 +141,15 @@ void pointing_mode_toggle_mode(uint8_t mode_id); // set toggle mode to mo
uint8_t pointing_mode_get_precision(void); // get active device precision
uint8_t pointing_mode_get_mode(void); // return active device mode_id
uint8_t pointing_mode_get_toggled_mode(void); // return active device toggle_id
void pointing_mode_reset(void); // reset active device mode_id to toggle_id
void pointing_mode_reset(void); // reset active device to current base settings

/* ----------Crontrolling pointing mode data---------------------------------------------------------------------- */
// Justify all the functions in this category
void pointing_mode_update(void); // update direction & divisor from current mode id, x, y
mouse_xy_report_t apply_divisor_xy(int16_t value); // divide value by current divisor and clamp to x/y range
int8_t apply_divisor_hv(int16_t value); // divide value by current divisor and clamps to h/v range
int16_t multiply_divisor_xy(mouse_xy_report_t value); // multiply mouse x/y value by current divisor
int16_t multiply_divisor_hv(int8_t value); // multiply mouse h/v value by current divisor

int16_t multiply_divisor_hv(int8_t value); // multiply mouse h/v value by current divisors
uint8_t current_pointing_mode_divisor(void); // access current divisor value
uint8_t current_pointing_mode_direction(void); // access current direction value

Expand All @@ -138,10 +159,10 @@ void pointing_tap_codes(uint16_t kc_left, uint16_t kc_down, uint16_t kc_up, uint
/* ----------Callbacks for modifying and adding pointing modes---------------------------------------------------- */
bool process_pointing_mode_kb(pointing_mode_t pointing_mode, report_mouse_t* mouse_report); // keyboard level
bool process_pointing_mode_user(pointing_mode_t pointing_mode, report_mouse_t* mouse_report); // user/keymap level

/* ----------Callbacks for adding/modifying pointing device mode divisors----------------------------------------- */
uint8_t get_pointing_mode_divisor_kb(uint8_t mode_id, uint8_t direction); // adding new divisors at keyboard level
uint8_t get_pointing_mode_divisor_user(uint8_t mode_id, uint8_t direction); // adding new divisors at user/keymap level
uint8_t get_pointing_mode_type_kb(uint8_t mode_id); // setting mode type at keyboard level
uint8_t get_pointing_mode_type_user(uint8_t mode_id); // setting mode type at user level
uint8_t get_pointing_mode_divisor_kb(uint8_t mode_id, uint8_t direction); // setting divisors at keyboard level
uint8_t get_pointing_mode_divisor_user(uint8_t mode_id, uint8_t direction); // setting divisors at user/keymap level

/* ----------Core functions (only used in custom pointing devices or key processing)------------------------------ */
void pointing_mode_set_device_settings(pointing_mode_device_t device); // set active device settings
Expand Down